WeChat payment interface docking document

Create a sub-package demo, create a controller package, domain package, and service package in the demo
Directory structure:
share picture
Share pictures

Create Pay_controller in the controller package
package com.ccunix .ihousekeeping.demo.controller;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotatio n.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ccunix.ihousekeeping.base.controller.BaseMultiController;
import com.ccunix.ihousekeeping.demo.domain.WxOa;
import com.ccunix.ihousekeeping.demo.service.UUID_Tools;
import com.ccunix.ihousekeeping.demo. service.WxSignUtil;
/**
*
* @ClassName: Pay_Controller
* @ author xyp
* @date 9:57:46 AM, August 12, 2019
*
*/
*
*/

div>

@Controller
@RequestMapping(“Pay_Controller”)
public class Pay_Controller extends BaseMultiController {
WxSignUtil wxSignUtil = new WxSignUtil();
// WeChat pre-order transaction
@ResponseBody
@RequestMapping(“/yuxiadan” )
public Map yuxiadan() throws Exception {
WxOa w xOa = new WxOa();
// Application ID
wxOa.setAppid(“xxxxxxxxxxxxxx”);
// Merchant ID

< div> wxOa.setMch_id(“xxxxxxxx”);

// The random string is not longer than 32 bits
wxOa.setNonce_str(UUID_Tools.getUUID());

< div> // Product description

wxOa.setBody(“phone”);
// Merchant order number
wxOa.setOut_trade_no(“12345”);
// Total order amount, in minutes
wxOa.setTotal_fee(10);
// Terminal IP
wxOa. setSpbill_create_ip(“127.0.0.1”);
// Notification address
wxOa.setNotify_url(wxSignUtil.unifiedorderUrl);
// Transaction type APP

div>

wxOa.setTrade_type(“NATIVE”);
// Put the data in the map
Map map = wxSignUtil.WxMd5Sign(wxOa, “9dffe0f7a65bb1976d4b33d7a8b1f7ac”);
//Convert to set collection
Set> entries = map.entrySet();
//Iterator Traverse
Iterator> iteratorMap = entries.iterator();
while (it eratorMap.hasNext()) {
Map.Entry next = iteratorMap.next();
System.err.println(next);
}
return map;
}
}
Create bean class in domain package:
WxOa class:
package com.ccunix .ihousekeeping.demo.domain;
import java.io.Serializable;
import java.util.Date;

< /div>

//WeChat pre-order parameters
public class WxOa implements Serializable {
// Application ID
private String appid;
// Merchant ID
private String mch_id;
// Device ID
private String device_info; < /div>

// The random string is not longer than 32 bits
private String nonce_str;
// Product description
private String body;
div>

// Additional data
private String attach;
// Merchant order number
private String out_trade_no;
// total order amount, in minutes
private int total_fee;
// terminal IP
private String spbill_create_ip;
// transaction start time
private Date time_start;
// transaction end time
private Date time_expire;
// notification address
private String notify_url;
// transaction type APP
private String trade_type; < /div>

// openid
private String openid;
//code_url
private String code_url;

div>

public String getCode_url() {
return code_url;
}
public void setCode_url(String code_url) {
this.code_url = code_url;
}
public String getAppid() {< /div>

return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getMch_id() {
return mch_id;
}

div>

public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}

div>

public String getDevice_info() {
return device_info;
}
public void setDevice_info(String device_info) {
this.device_info = device_info;
}
public String getNonce_str() {
return nonce_str;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;

< div>}

public String getBody() {
return body;
}

div>

public void setBody(String body) {
this.body = body;
}
public StringgetAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getOut_trade_no() {
return out_trade_no;

< div>}

public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public int getTotal_fee() {
return total_fee;
}
public void setTotal_fee(int total_fee) {
this.total_fee = total_fee;
}
public String getSpbill_create_ip() {
return spbill_create_ip;
}
public void setSpbill_create_ip(String spbill_create_ip) {
this.spbill_create_ip = spbill_create_ip;
}
public Dat e getTime_start() {
return time_start;
}
public void setTime_start(Date time_start) {

< div> this.time_start = time_start;

}
public Date getTime_expire() {
return time_expire;
}
public void setTime_expire(Date time_expire) {
this.time_expire = time_expire;
}
public String getNotify_url() {
return notify_url;
}
public void setNotify_url(String notify_url) {
this.notify_url = notify_url;
}
public String getTrade_type() {

return trade_type;
}
public void setTrade_type(String trade_type) {
this.trade_type = trade_type ;
}
public String getOpe nid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
}
WxPayOa class:
package com.ccunix.ihousekeeping.demo.domain;
import java.io.Serializable;
public class WxPayOa implements Serializable {
// Application ID
private String appid; < /div>

// random string
private String noncestr;
// extension field
private String packageace;
// Merchant ID
private String partnerid;
// Prepayment transaction session ID
private String prepayid;
// Timestamp
private String timestamp;
public String getAppid() {
return appid;
}
public v oid setAppid(String appid) {
this.appid = appid;
}
public String getNoncestr() {

return noncestr;
}
public void setNoncestr(String noncestr) {
this.noncestr = noncestr ;
}
public String getPackageace() {
return packageace;
}
public void setPackageace(String packageace) {
this.packageace = packageace;
}
public String getPartnerid() {
return partnerid;
}
public void setPartnerid(String partnerid) {
this.partnerid = partnerid;
}
public String getPrepayid() {
return prepayid ;
}
public void setPrepayid(String prepayid) {
t his.prepayid = prepayid;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}

< div>

}
The service package contains the tool class, and the important one is the WxSignUtil class
WxSignUtil class:
package com.ccunix.ihousekeeping.demo.service;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.HashMap;
import java.security.KeyStore;
import java.util.HashMap;

div>

import java.util.List;
import java.util.Map;
import javax.crypto.spec.SecretKeySpec;

< div> import javax.net.ssl.SSLContext;

import javax.servlet.http.HttpServletRequest;
import org.apache.commons.httpclient.HttpClient;

< div> import org.apache.commons.httpclient.HttpStatus;

import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.http.HttpEntity; < /div>

import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client .methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;

< div> 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.DocumentException; < /div>

import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import com.alibaba.fastjson.JSONObject;
import com. ccunix.ihousekeeping.demo.domain.WxOa;
import com.ccunix.ihousekeeping.demo.domain.WxPayOa;
//WeChat signature

div>

public class WxSignUtil {
// WeChat pre-order request address
public static final String unifiedorderUrl = “https://api .mch.weixin.qq.com/pay/unifiedorder”;
// WeChat refund request address
public static final String callbackamounturl = ” https://api.mch.weixin.qq.com/secapi/pay/refund”;
// WeChat mini program unified order address
public static final String smallprogramorderurl = “https://api.mch.weixin.qq.com/pay/unifiedorder”;
// WeChat App payment pre-order interface
public static Map WxMd5Sign(WxOa wxOa, String key) throws Exception {
String stringA = “appid=” + wxOa.getAppid() + “&attach=” + wxOa.getAttach() + “&body=” + wxOa.getBody()
+ “&mch_id=” + wxOa.getMch_id() + “&nonce_str=” + wxOa.getNonce_str() + “&notify_url=”
+ wxOa.getNotify_url() + “&out_trade_no=” + wxOa.getOut_trade_no() + “&spbill_create_ip=”
+ wxOa.getSpbill_create_ip() + “&total_fee =” + wxOa.getTotal_fee() + “&trade_type=”
+ wxOa.getTrade_type();
String stringSignTemp = stringA + “&key=” + key;
String stringSignTemp1 = new String(stringSignTemp.getBytes(“iso8859-1”));
// String stringSignTemp1=new String(stringSignTemp.getBytes(“utf-8”));

String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
String par = “” + “” + wxOa.getAppid() + “” + “” + wxOa.getAttach() + “
+ “” + “” + wxOa.getMch_id() + “
+ “” + wxOa.getNon ce_str() + “” + “” + wxOa.getNotify_url()
+ “” + “” + wxOa.getOut_trade_no() + ” ” + “
+ wxOa.getSpbill_create_ip() + “” + “” + wxOa.getTotal_fee()
+ “” + “” + wxOa.getTrade_type() + “” + “” + sign + “
+ ” “;
String ret = WxSignUtil.post(unifiedorderUrl, par);
System.out.println(ret);
Map map = readStringXmlOut(ret);
return map;
}
// Call up payment and sign
public static String WxPrePaySign(WxPayOa wxPayOa, String key) throws Exception {
// //App ID
// String appid=””;
// //Random string
// String noncestr=””;
// //Extension field
div>
// String packageace=””;
// // Merchant ID
// String partnerid=””;
// //Prepayment transaction session ID
// String prepayid=””;
// //time stamp
// String timestamp=””;
String stringA = “appid=” + wxPayOa.getAppid() + “&noncestr= “+ wxPayOa.getNoncestr() + “&package=”
+ wxPayOa.getPackageace() + “&partnerid=” + wxPayOa.getPartnerid() + “&prepayid=”
+ wxPayOa .getPrepayid() + “&timestamp=” + wxPayOa.getTimestamp();
String stringSignTemp = stringA + “&key=” + key;
String stringSignTemp1 = new String(stringSignTemp. getBytes(“iso8859-1”));
// String stringSignTemp1=new String(stringSignTemp.getBytes(“utf-8”));
String sign = LogisticsInfoMD5.encode (stringSignTemp1).toUpperCase();
return sign;
}
/**
* Send xml data request to the server side
*
* @param url
* xml request data address
* @param xmlString
* The sent xml data stream
* @return null Sending failed, otherwise the response content will be returned
*/
public static String post(String url , String xmlFileName) {
// Close
System.setProperty(“org.apache.commons.logging.Log”, “org.apache.commons.logging.impl.SimpleLog “);
System.setProperty(“org.apache.commons.logging.simplelog.showdatetime”, “true”);
System.setProperty(“org.apache.commons .logging.simplelog.log.org.apache.commons.httpclient”, “stdout”);
// Create httpclient tool object
HttpClient client = new HttpClient();
// Create a post request method
PostMethod myPost = new PostMethod(url);
// Set the request timeout period
div>
client.setConnectionTimeout(300 * 1000);
String responseString = null;
try {
// Set the request header type< /div>
myPost.setRequestHeader(“Content-Type”, “text/xml”);
myPost.setRequestHeader(“charset”, “iso8859-1”);
< div> / / myPost.setRequestHeader(“charset”,”utf-8″);
// Set the request body, that is, the xml text content. Note: Two methods are written here, One is to directly obtain the xml content string, the other is to read the xml file in the form of a stream
myPost.setRequestBody(xmlFileName);
/ / InputStream body=this.getClass().getResourceAsStream(“/”+xmlFileName);
// myPost.setRequestBody(body);
// myPost.setRequestEntity(new < /div>
// StringRequestEntity(xmlString,”text/xml”,”utf-8″));
int statusCode = client.executeMethod(myPost);
if (statusCode == HttpStatus.SC_OK) {
BufferedInputStream bis = new BufferedInputStream(myPost.getResponseBodyAsStream());
byte[] bytes = new byte[1024];
div>
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int count = 0;
while ((count = bis.read(bytes)) != -1) {
bos.write(bytes, 0, count);
}
byte[] strByte = bos.toByteArray();
responseString = new String(strByte, 0, strByte.length, “utf-8”);
// System.out.println(responseString);
bos.close();
bis.close();
}
} catch (Exception e) {
e.printStackTrace();
div>
}
myPost.releaseConnection();
return responseString;
}
/**
* @description converts xml string into map
* @param xml
* @return Map
*/
public static Map readStringXmlOut(String xml) {
Map map = new HashMap();
Document doc = null;
try {
doc = DocumentHelper.parseText(xml); // Convert the string to XML
Element rootElt = doc.getRootElement(); // Get the root node
@SuppressWarnings(“unchecked”)
List list = rootElt.elements();// Get All nodes under the root node
for (Element element: list) {// Traverse the node
map.put(element.getName(), element.getText()); // The name of the node is the key of the map, and the text is the value of the map
} < /div>
} catch (DocumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace ();
}
return map;
}
// Payment callback verification signature< /div>
public static boolean wxPayChack(Map map, String key) throws Exception {
String stringA = “appid=” + map.get(“appid”) + “&attach=” + map .get(“attach”) + “&bank_type=”
+ map.get(“bank_type”) + “&cash_fee=” + map.get(“cash_fee”) + “” + “&fee_type=” + map.get(“fee_type”)
+ “&is_subscribe=” + map.get(“is_subscribe”) + “&mch_id=” + map.get(“mch_id”) + “&nonce_str=” < /div>
+ map.get(“nonce_str”) + “&openid=” + map.get(“openid”) + “&out_trade_no=” + map.get(“out_trade_no”)
+ “&result_code=” + map.get(“result_code”) + “&return_code=” + map.get(“return_co de”) + “&time_end=”
+ map.get(“time_end”) + “&total_fee=” + map.get(“total_fee”) + “&trade_type=” + map.get(“trade_type “)
+ “&transaction_id=” + map.get(“transaction_id”);
String stringSignTemp = stringA + “&key=” + key;
String stringSignTemp1 = new String(stringSignTemp.getBytes(“iso8859-1”));
String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
String retSign = ( String) map.get(“sign”);
if (retSign.equals(sign)) {
return true;
}
return false;
}
// Receive WeChat callback request to obtain xml parameter information
public static Map inputStream2String(HttpServletRequest request) throws Exception {
InputStream is = request.getInputStream();
String xml = WxSignUtil.inputStream2String(is, “utf-8”);
return WxSignUtil.readStringXmlOut(xml);
}
< div>
/**
* Convert InputStream into String string
*
* @param inStream
* InputStream stream
* @param encoding
* encoding format
* @return String string
*/ < /div>
public static String inputStream2String(InputStream inStream, String encoding) {
String result = null;
try {
if (inStream! = null) {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] tempBytes = new byte[1000];
int count = -1;
while ((count = inStream.read(tempBytes, 0, 1000)) != -1) {
outStream.write(tempBytes, 0, count);
}
tempBytes = null;
outStream.flush();
result = new String(outStream.toByteArray(), encoding);
}
} catch (Exception e) {
result = null;
}
return result ;
}
// Get the user’s openid
public static String getUserOpenId(Map map) {
String param = “appid=” + map.get(“openappid”) + “&secret=” + map.get(“opensecret”) + “&code=” + map.get(“code”)
+ “&grant_type=authorization_code”;
String ret = HttpUtil.doGet(map.get(“openidurl”), param);
JSONObject jon = JSONObject. parseObject(ret);
String openId = jon.getString(“openid”);
return openId;
}
​ < /div>
// WeChat public account pre-order
public static Map WxH5Md5Sign(Map map, String key) throws Exception {
// //Public account ID < /div>
// String appid=””;
// //Product description
// String body=””;
/ / //Merchant ID
// String mch_id=””;
// //Random string
// String nonce_str=””; < /div>
// //Notification address
// String notify_url=””;
// //User ID
// String openid=””;
// //Merchant order number
// String out_trade_no=””;
// //Terminal IP
// String spbill_create_ip=””;
// //Total order amount
// int total_fee=0;
// //Transaction type
// String trade_type=””;
String stringA = “appid=” + map.get (“openappid”) + “&body=” + map.get(“body”) + “&mch_id=”
+ map.get(“openmchid”) + “&nonce_str=” + map.get( “nonce_str”) + “&notify_url=”
+ map.get(“opencallbackurl”) + “&openid=” + map.get(“openid”) + “&out_trade_no=”
+ map.get(“out_trade_no”) + “&spbill_create_ip=127.0.0.1&total_fee=” + map.get(“total_fee”)
+ “&trade_type=JSAPI”;
String stringSignTemp = stringA + “&key=” + key;
// String stringSignTemp1=new String(stringSignTemp.getBytes(“iso8859-1”));
String stringSignTemp1 = new String(stringSignTemp.getBytes(“utf-8”));
String si gn = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
String par = “” + “” + “
+ map.get(“openmchid”) + “]]>” + “
+ “” + “
+ “]] >” + “
+ “
+ “ “+ “
+ map.get(“total_fee”) + “]]>” + “” + “
+ sign + “” + ““;
// B8971A5E8220F8B9A1C314FDDA7440C4
String ret = WxSignUtil.post(“https ://api.mch.weixin.qq.com/pay/unifiedorder”, par);
Map mapret = readStringXmlOut(ret);
return mapret ;
}
// Official account pre-order callback verification signature
public static boolean orderPayCallbackChack(Map map, String key ) throws Exception {
String stringA = “appid=” + map.get(“appid”) + “&bank_type=” + map.get(“bank_type”) + “&cash_fee=”
+ map.get(“cash_fee”) + “&fee_type=” + map.get(“fee_type”) + “&is_subscribe=” + map.get(“is_subscribe”)
+ “&mch_id =” + map.get(“mch_id”) + “&nonce_str=” + map.get(“nonce_str”) + “&openid=” + map.get(“openid”)
+ “&out_trade_no= “+ map.get(“out_trade_no”) + “&result_code=” + map.get(“result_code”)
+ “&return_code=” + map.get(“return_code”) + “&time_end=” + map.get(“time_end”) + “&total_fee=”
+ map.get(“total_fee”) + “&trade_type=” + map.get(“trade_type”) + “&transaction_id=” < /div>
+ map.get(“transacti on_id”);
String stringSignTemp = stringA + “&key=” + key;
String stringSignTemp1 = new String(stringSignTemp.getBytes(“utf-8”));
String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
String retsign = map.get(“sign”) + “”;
if ( sign.equals(retsign)) {
return true;
}
return false;
}
// Official account calls up payment signature
public static String openSignPayMd5(Map map, String key) throws Exception {
// Official account id < /div>
String appId = “”;
// Timestamp
String timeStamp = “”;
// Random string
div>
String nonceStr = “”;
// Order details expansion string
String packageout = “”;
// Signature method< /div>
String signType = “”;
// String
// stringA=”appid=wx8731a2e298f48739&nonceStr=123456&package=123456&signType=MD5&timeStamp =123 456″;
String stringA = “appId=” + map.get(“appId”) + “&nonceStr=” + map.get(“nonceStr”) + “&package=”
< div> + map.get(“package”) + “&signType=” + map.get(“signType”) + “&timeStamp=” + map.get(“timeStamp”);
String stringSignTemp = stringA + “&key=” + key;
// String stringSignTemp1=new String(stringSignTemp.getBytes(“iso8859-1”));
String stringSignTemp1 = new String(stringSignTemp .getBytes(“utf-8”));
String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
return sign;
}
// WeChat payment merchant refund
public static Map wxPayMachBackToUser(Map map, String key) throws Exception {
public static Map wxPayMachBackToUser(Map map, String key) throws Exception {
/div>
// //Public account ID
// String appid=””;
// //Merchant ID
// String mch_id=””;
// //Random string
// String nonce_str=””;
// //WeChat order number serial Number
// String transaction_id=””;
//// //Merchant order number
//// String out_trade_no=””;
// //Merchant refund order number
// String out_refund_no=””;
// //Order amount The total amount of the order, in minutes, only integers
// String total_fee=” “;
// //Refund amount
// String refund_fee=””;
// Refund result notification url
< div> // String notify_url=””;
String stringA = “appid=” + map.get(“appid”) + “&mch_id=” + map.get( “mch_id”) + “&nonce_str=”
+ map.get(“nonce_str”) + “&notify_url=” + map.get(“notify_url”) + “&out_refund_no=”
+ map.get(“out_refund_no”) + “&refund_fee=” + map.get(“refund_fee”) + “&total_fee=”
+ map.get(“total_fee”) + “&transaction_id=” + map.get(“transaction_id”);
String stringSignTemp = stringA + “&key=” + key;
// String stringSignTemp1=new String (stringSignTemp.getBytes(“iso8859-1”));
String stringSignTemp1 = new String(stringSignTemp.getBytes(“utf-8”) );
String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
String par = “” + “ ” + “
+ map.get(“mch_id “) + “]]>” + “
+ “]]>” + “
+”
+ ” ” + ”
+ map.get(“total_fee”) + “]]>” + ”
+ “]]>” + ” ” + sign + “” + ““;
 
// String ret=WxSignUtil.post(“https://api.mch.weixin.qq.com/secapi/pay/refund”,

< div> // par);

String ret = WxSignUtil .postData(“https://api.mch.weixin.qq.com/secapi/pay/refund”, par, map.get(“mch_id”) + “”,
map.get(“keyPath”) + “”);
Map mapret = readStringXmlOut(ret);
return mapret;
}
 
// 解密微信退款加密字段
public static Map desDecodeWxPayCallBack(Map map, String key) throws Exception {
// 对商户key做md5,得到32位小写key*
// String mdkey=LogisticsInfoMD5.encode(key).toLowerCase();
SecretKeySpec mdkey = new SecretKeySpec(LogisticsInfoMD5.encode(key).toLowerCase().getBytes(), “AES”);
 
// 微信订单号
String transaction_id = map.get(“transaction_id”);
if (transaction_id != null) {
// 对加密串A做base64解码,得到加密串B
transaction_id = new String(Base64Util.decode(transaction_id));
transaction_id = AESUtil.decryptData(transaction_id, mdkey);
map.put(transaction _id, transaction_id);
}
return map;
}
 
private static int socketTimeout = 10000;// 连接超时时间,默认10秒
private static int connectTimeout = 30000;// 传输超时时间,默认30秒
private static RequestConfig requestConfig;// 请求器的配置
private static CloseableHttpClient httpClient;// HTTP请求器
 
/**
* 通过Https往API post xml数据
*
* @param url
* API地址
* @param xmlObj
* 要提交的XML数据对象
* @param mchId
* 商户ID
* @param certPath
* 证书位置
* @return
*/
public static String postData(String url, String xmlObj, String mchId, String certPath) {
// 加载证书
try {
initCert(mchId, certPath);
} catch (Exception e) {
e.printStackTrace();
}
String result = null;
HttpPost httpPost = new HttpPost(url);
// 得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
StringEntity postEntity = new StringEntity(xmlObj, “UTF-8”);
httpPost.addHeader(“Content-Type”, “text/xml”);
httpPost.setEntity(postEntity);
// 根据默认超时限制初始化requestConfig
requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout)
.build();
// 设置请求器的配置
httpPost.setConfig(requestConfig);
try {
HttpResponse response = null;
try {
response = httpClient.execute(httpPost);
} catch (IOException e) {
e.printStackTrace();
}
HttpEntity entity = response.getEntity();
try {
result = EntityUtils.toString(entity, “UTF-8”);
} catch (IOException e) {
e.printStackTrace();
}
} finally {
httpPost.abort();
}
return result;
}
 
/**
* 加载证书
*
* @param mchId
* 商户ID
* @param certPath
* 证书位置
* @throws Exception
*/
private static void initCert(String mchId, String certPath) throws Exception {
// 证书密码,默认为商户ID
String key = mchId;
// 证书的路径
String path = certPath;
// 指定读取证书格式为PKCS12
KeyStore keyStore = KeyStore.getInstance(“PKCS12”);
// 读取本机存放的PKCS12证书文件
FileInputStream instream = new FileInputStream(new File(path));
try {
// 指定PKCS12的密码(商户ID)
keyStore.load(instream, key.toCharArray());
} finally {
instream.close();
}

SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, key.toCharArray()).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { “TLSv1” }, null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
}
 
// 微信小程序統一下單
public static Map WxSmallProgramMd5Sign(Map map, String key) throws Exception {
String stringA = “appid=” + map.get(“appid”) + “&attach=” + map.get(“attach”) + “&body=” + map.get(“body”)
+ “&mch_id=” + map.get(“mch_id”) + “&nonce_str=” + map.get(“nonce_str”) + “&notify_url=”
+ map.get(“notify_url”) + “&openid=” + map.get(“openid”) + “&out_trade_no=” + map.get(“out_trade_no”)
+ “&spbill_create_ip=” + map.get(“spbill_create_ip”) + “&total_fee=” + map.get(“total_fee”)

+ “&trade_type=” + map.get(“trade_type”);
 
String stringSignTemp = stringA + “&key=” + key;
String stringSignTemp1 = new String(stringSignTemp.getBytes(“iso8859-1”));
// String stringSignTemp1=new String(stringSignTemp.getBytes(“utf-8”));
String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
 
String par = “” + “” + map.get(“appid”) + “” + “” + map.get(“attach”) + “
+ “” + map.get(“body”) + “” + “” + map.get(“mch_id”) + “” + “
+ map.get(“nonce_str”) + “” + “” + map.get(“notify_url”) + “
+ “” + map.get(“openid”) + “” + “” + map.get(“out_trade_no”)
+ “” + “” + map.get(“spbill_create_ip”) + “
+ “< total_fee>” + map.get(“total_fee”) + “” + “” + “JSAPI” + “
+ “” + sign + “” + ““;
String ret = WxSignUtil.post(smallprogramorderurl, par);
Map retmap = readStringXmlOut(ret);
return retmap;
}
 
// 微信小程序调起支付签名
public static Map wxSmallProgramPaySign(Map map, String key) throws Exception {
String stringA = “appId=” + map.get(“appid”) + “&nonceStr=” + map.get(“nonceStr”) + “&package=prepay_id=”
+ map.get(“prepay_id”) + “&signType=MD5&timeStamp=” + map.get(“timeStamp”);
 
String stringSignTemp = stringA + “&key=” + key;
String stringSignTemp1 = new String(stringSignTemp.getBytes(“iso8859-1”));
// String stringSignTemp1=new String(stringSignTemp.getBytes(“utf-8”));
String sign = LogisticsInfoMD5.encode(stringSign Temp1).toUpperCase();
 
Map retmap = new HashMap();
retmap.put(“time”, map.get(“timeStamp”));
retmap.put(“package”, “prepay_id=” + map.get(“prepay_id”));
retmap.put(“paySign”, sign);
retmap.put(“signType”, “MD5”);
retmap.put(“nonceStr”, map.get(“nonceStr”));
return retmap;
}
 
// 微信小程序获得openid
public static String wxSmallProgramGetOpenId(Map map, String secret) throws Exception {
String getUrl = “https://api.weixin.qq.com/sns/jscode2session”;
String param = “appid=” + map.get(“appid”) + “&secret=” + secret + “&js_code=” + map.get(“code”)
+ “&grant_type=authorization_code”;
String ret = HttpUtil.doGet(getUrl, param);
// {“session_key”:”vz5yE67kF3p8CKpTtLgobw==”,”openid”:”oMEFK5M53RmMPTow1_GoBRKkrOI4″}
JSONObject json = JSONObject.parseObje ct(ret);
String openid = json.getString(“openid”);
String session_key = json.getString(“session_key”);
return openid + “,” + session_key;
}
 
// 查询微信订单
public static void queryOrderPayInfo() throws Exception {
String stringA = “appid=wx608bbf2ae0956623&mch_id=1512285851&nonce_str=456168546545&out_trade_no=0a3f639a3f174529a7ca236632f36d4d&key=9dffe0f7a65bb1976d4b33d7a8b1f7ac”;
String stringSignTemp = stringA;
String stringSignTemp1 = new String(stringSignTemp.getBytes(“utf-8”));
String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();
 
String par = “” + “
+ “” + “
+ “” + “” + sign
+ “” + ““;
String ret = WxSignUtil.post(“https://api.mch.weixin.qq.com/pay/orderquery”, par);
Map mapret = readStringXmlOut(ret);
System.out.println(mapret);
}
 
}
 
 
pom.xml:
 
 
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
4.0.0
 
isweb
ccunix.is
0.0.1-SNAPSHOT
war
 
 
 
4.0.2.RELEASE
3.2.8
1.7.12
1.2.17
junit
junit
3.8.1
test
javax
javaee-api
provided
7.0
org.springframework
spring-test
${srping.version}
org.springframework
spring-core
${srping.version}
com.google.zxing
javase
3.3.3
 
org.apache.httpcomponents
httpclient
 
org.springframework
spring-oxm
${srping.version}
org.springframework
spring-tx
${srping.version}
org.springframework
spring-jdbc
${srping.version}
org.springframework
spring-aop
${srping.version}
org.springframework
spring-context
${srping.version}
org.springframework
spring-context-support
${srping.version}
org.springframework
spring-expression
${srping.version}
org.springframework
spring-orm
${srping.version}
org.springframework
spring-web
${srping.version}
org.springframework
spring-webmvc
${srping.version}
org.mybatis
mybatis
${mybatis.version}

org.mybatis
mybatis-spring
1.2.2
 
mysql
mysql-connector-java
5.1.35
commons-dbcp
commons-dbcp
1.4
jstl
jstl
1.2
 

com.belerweb
pinyin4j
2.5.0
 
log4j
log4j
${log4j.version}
org.slf4j
slf4j-api
${slf4j.version}
org.slf4j
slf4j-log4j12
${slf4j.version}
 
com.alibaba
fastjson
1.2.6
org.codehaus.jackson
jackson-mapper-asl
1.9.13
 
com.fasterxml.jackson.core
jackson-databind
2.4.2
 
 
commons-fileupload
commons-fileupload
1.3.1
commons-io
commons-io
2.4
commons-codec
commons-codec
1.10
org.aspectj
aspectjweaver
1.6.12
org.springframework.data
spring-data-redis
1.0.2.RELEASE
org.springframework
spring-test
3.1.2.RELEASE
test
redis.clients
jedis
2.1.0
 
 
org.eclipse.paho
org.eclipse.paho.client.mqttv3
1.2.0
commons-codec
commons-codec
1.10
 
org.json
json
20090211
 
org.apache.httpcomponents
httpclient
4.3.5
 
 
org.apache.poi
poi
3.9
org.apache.poi
poi-ooxml
3.9
 
 
 
org.hibernate
hibernate-validator
5.3.0.Alpha1
org.slf4j
slf4j-api
1.7.21
 
org.slf4j
slf4 j-log4j12
1.7.21
org.bouncycastle
bcprov-jdk15on
1.55
commons-codec
commons-codec
1.10
 
dom4j
dom4j
1.6.1
 
com.baidu.aip
java-sdk
4.8.0
 

< div>  

 
org.apache.maven.plugins
maven-compiler-plugin
1.7
1.7
 
org.apache.maven.plugins
maven-war-plugin
3.0.0
 
maven_project
 
 
 
 
 
 
点击支付页面:demo.jsp
 
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding= “UTF-8″%>
<%@include file="/WEB-INF/html/base/baseurl.jsp"%>
Insert title here

微信支付

 
 
 
 
 
生成二维码页面:qrcode.jsp
 
 
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding=”UTF-8″%>
<%@include file="/WEB-INF/html/base/baseurl.jsp"%>
Javascript 二维码生成库:QRCode
<%
out.print(“<%=request.getAttribute("param") %><% out.print("\"");
%>
content=”width=device-width,initial-scale=1,user-scalable=no” />

 
 
 
注意:appid需要跟商户号绑定

建立子包demo,demo里面创建controller包、domain包、service包

目录结构:

分享图片

  分享图片

 

 

controller包中创建Pay_controller

 

package com.ccunix.ihousekeeping.demo.controller;

 

import java.io.IOException;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.util.Set;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import or g.springframework.web.bind.annotation.ResponseBody;

import com.ccunix.ihousekeeping.base.controller.BaseMultiController;

import com.ccunix.ihousekeeping.demo.domain.WxOa;

import com.ccunix.ihousekeeping.demo.service.UUID_Tools;

import com.ccunix.ihousekeeping.demo.service.WxSignUtil;

 

/**

*

* @ClassName: Pay_Controller

* @author xyp

* @date 2019年8月12日 上午9:57:46

*

*/

 

@Controller

@RequestMapping(“Pay_Controller”)

public class Pay_Controller extends BaseMultiController {

 

WxSignUtil wxSignUtil = new WxSignUtil();

 

// 微信预下单交易

@ResponseBody

@RequestMapping(“/yuxiadan”)

public Map yuxiadan() throws Exception {

WxOa wxOa = new WxOa();

// 应用ID

wxOa.setAppid(“xxxxxxxxxxxxxx”);

// 商户号

wxOa.setMch_id(“xxxxxxxx”);

// 随机字符串 不长于32位

wxOa.setNonce_str(UUID_Tools.getUUID());

// 商品描述

wxOa.setBody(“phone”);

// 商户订单号

wxOa.setOut_trade_no(“12345”);

// 订单总金额,单位为分

wxOa.setTotal_fee(10);

// 终端IP

wxOa.setSpbill_create_ip(“127.0.0.1”);

// 通知地址

wxOa.setNotify_url(wxSignUtil.unifiedorderUrl);

// 交易类型 APP

wxOa.setTrade_type(“NATIVE”);

// 将数据放入map中

Map map = wxSignUtil.WxMd5Sign(wxOa, “9dffe0f7a65bb1976d4b33d7a8b1f7ac”);

//转换为set集合

Set> entries = map.entrySet();

//迭代器进行遍历

Iterator> iteratorMap = entries.iterator();

while (iteratorMap.hasNext()) {

Map.Entry next = iteratorMap.next();

System.err.println(next);

}

return map;

}

 

}

 

 

domain包中创建bean类:

 

WxOa类:

 

package com.ccunix.ihousekeeping.demo.domain;

 

import java.io.Serializable;

import java.util.Date;

 

//微信预下单参数

public class WxOa implements Serializable {

 

// 应用ID

private String appid;

// 商户号

private String mch_id;

// 设备号

private String device_info;

// 随机字符串 不长于32位

private String nonce_str;

// 商品描述

private String body;

// 附加数据

private String attach;

// 商户订单号

private String out_trade_no;

// 订单总金额,单位为分

private int total_fee;

// 终端IP

private String spbill_create_ip;

// 交易起始时间

private Date time_start;

// 交易结束时间

private Date time_expire;

// 通知地址

private String notify_url;

// 交易类型 APP

private String trade_type;

// openid

private String openid;

//code_url

private String code_url;

 

 

public String getCode_url() {

return code_url;

}

 

public void setCode_url(String code_url) {

this.code_url = code_url;

}

 

public String getAppid() {

return appid;

}

 

public void setAppid(Str ing appid) {

this.appid = appid;

}

 

public String getMch_id() {

return mch_id;

}

 

public void setMch_id(String mch_id) {

this.mch_id = mch_id;

}

 

public String getDevice_info() {

return device_info;

}

 

public void setDevice_info(String device_info) {

this.device_info = device_info;

}

 

public String getNonce_str() {

return nonce_str;

}

 

public void setNonce_str(String nonce_str) {

this.nonce_str = nonce_str;

}

 

public String getBody() {

return body;

}

 

public void setBody(String body) {

this.body = body;

}

 

public String getAttach() {

return attach;

}

 

public void setAttach(String attach) {

this.attach = attach;

}

 

public String getOut_trade_no() {

return out_trade_no;

}

 

public void setOut_t rade_no(String out_trade_no) {

this.out_trade_no = out_trade_no;

}

 

public int getTotal_fee() {

return total_fee;

}

 

public void setTotal_fee(int total_fee) {

this.total_fee = total_fee;

}

 

public String getSpbill_create_ip() {

return spbill_create_ip;

}

 

public void setSpbill_create_ip(String spbill_create_ip) {

this.spbill_create_ip = spbill_create_ip;

}

 

public Date getTime_start() {

return time_start;

}

 

public void setTime_start(Date time_start) {

this.time_start = time_start;

}

 

public Date getTime_expire() {

return time_expire;

}

 

public void setTime_expire(Date time_expire) {

this.time_expire = time_expire;

}

 

public String getNotify_url() {

return notify_url;

}

 

public void setNotify_url(String notify_url) {

this.notify_url = notify_url;

}

 

public String getTrade_type() {

return trade_type;

}

 

public void setTrade_type(String trade_type) {

this.trade_type = trade_type;

}

 

public String getOpenid() {

return openid;

}

 

public void setOpenid(String openid) {

this.openid = openid;

}

 

}

 

 

WxPayOa类:

 

package com.ccunix.ihousekeeping.demo.domain;

 

import java.io.Serializable;

 

public class WxPayOa implements Serializable {

 

// 应用ID

private String appid;

// 随机字符串

private String noncestr;

// 扩展字段

private String packageace;

// 商户号

private String partnerid;

// 预支付交易会话ID

private String prepayid;

// 时间戳

private String timestamp;

 

public String getAppid() {

return appid;

}

 

public void setAppid(String appid) {

this.appid = a ppid;

}

 

public String getNoncestr() {

return noncestr;

}

 

public void setNoncestr(String noncestr) {

this.noncestr = noncestr;

}

 

public String getPackageace() {

return packageace;

}

 

public void setPackageace(String packageace) {

this.packageace = packageace;

}

 

public String getPartnerid() {

return partnerid;

}

 

public void setPartnerid(String partnerid) {

this.partnerid = partnerid;

}

 

public String getPrepayid() {

return prepayid;

}

 

public void setPrepayid(String prepayid) {

this.prepayid = prepayid;

}

 

public String getTimestamp() {

return timestamp;

}

 

public void setTimestamp(String timestamp) {

this.timestamp = timestamp;

}

 

}

 

service包中为工具类,其中重要的为WxSignUtil类

 

WxSignUtil类:

 

package com.ccunix.ihousekeeping.demo.service;

 

import java.io.BufferedInputStream;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.security.KeyStore;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import javax.crypto.spec.SecretKeySpec;

import javax.net.ssl.SSLContext;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.httpclient.HttpClient;

import org.apache.commons.httpclient.HttpStatus;

import org.apache.commons.httpclient.methods.PostMethod;

import org.apache.http.HttpEntity;

import org.apache.http.HttpResponse;

import org.apache.http.client.config.RequestConfig;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;

import org.apache.htt p.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.DocumentException;

import org.dom4j.DocumentHelper;

import org.dom4j.Element;

import com.alibaba.fastjson.JSONObject;

import com.ccunix.ihousekeeping.demo.domain.WxOa;

import com.ccunix.ihousekeeping.demo.domain.WxPayOa;

 

//微信签名

public class WxSignUtil {

 

// 微信预下单 请求地址

public static final String unifiedorderUrl = “https://api.mch.weixin.qq.com/pay/unifiedorder”;

 

// 微信申请退款请求地址

public static final String callbackamounturl = “https://api.mch.weixin.qq.com/secapi/pay/refund”;

 

// 微信小程序统一下单地址

public static final String smallprogramorderurl = “https://api.mch.weixin.qq.com/pay/unifiedorder”;

 

// 微信App支付预下单接口

public static Map WxMd5Sign(WxOa wxOa, String key) throws Exception {

String stringA = “appid=” + wxOa.getAppid() + “&attach=” + wxOa.getAttach() + “&body=” + wxOa.getBody()

+ “&mch_id=” + wxOa.getMch_id() + “&nonce_str=” + wxOa.getNonce_str() + “&notify_url=”

+ wxOa.getNotify_url() + “&out_trade_no=” + wxOa.getOut_trade_no() + “&spbill_create_ip=”

+ wxOa.getSpbill_create_ip() + “&total_fee=” + wxOa.getTotal_fee() + “&trade_type=”

+ wxOa.getTrade_type();

String stringSignTemp = stringA + “&key=” + key;

String stringSignTemp1 = new String(stringSignTemp.getBytes(“iso8859-1”));

// String stringSignTemp1=new String(stringSignTemp.getBytes(“utf-8”));

String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();

String par = “” + “” + wxOa.getAppid() + “” + “” + wxOa.getAttach() + “

+ “” + “” + wxO a.getMch_id() + “

+ “” + wxOa.getNonce_str() + “” + “” + wxOa.getNotify_url()

+ “” + “” + wxOa.getOut_trade_no() + “” + “

+ wxOa.getSpbill_create_ip() + “” + “” + wxOa.getTotal_fee()

+ “” + “” + wxOa.getTrade_type() + “” + “” + sign + “

+ “ “;

 

String ret = WxSignUtil.post(unifiedorderUrl, par);

System.out.println(ret);

Map map = readStringXmlOut(ret);

return map;

}

 

// 调起支付加签

public static String WxPrePaySign(WxPayOa wxPayOa, String key) throws Exception {

// //应用ID

// String appid=””;

// //随机字符串

// String noncestr=””;

// //扩展字段

// String packageace=””;

// //商户号

// String partnerid=””;

// //预支付交易会话ID

// String prepayid=””;

// //时间戳

// String timestamp=””;

String stringA = “appid=” + wxPayOa.getAppid() + “&noncestr=” + wxPayOa.getNoncestr() + “&package=”

+ wxPayOa.getPackageace() + “&partnerid=” + wxPayOa.getPartnerid() + “&prepayid=”

+ wxPayOa.getPrepayid() + “&timestamp=” + wxPayOa.getTimestamp();

String stringSignTemp = stringA + “&key=” + key;

String stringSignTemp1 = new String(stringSignTemp.getBytes(“iso8859-1”));

// String stringSignTemp1=new String(stringSignTemp.getBytes(“utf-8”));

String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();

return sign;

}

 

/**

* 发送xml数据请求到server端

*

* @param url

* xml请求数据地址

* @param xmlString

* 发送的xml数据流

* @return null发送失败,否则返回响应内容

*/

public static String post(String url, String xmlFileName) {

// 关闭

System.setProperty(“org.apache.commons.logging.Log”, “org.apache.commons.logging.impl.SimpleLog”);

System.setProperty(“o rg.apache.commons.logging.simplelog.showdatetime”, “true”);

System.setProperty(“org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient”, “stdout”);

 

// 创建httpclient工具对象

HttpClient client = new HttpClient();

// 创建post请求方法

PostMethod myPost = new PostMethod(url);

// 设置请求超时时间

client.setConnectionTimeout(300 * 1000);

String responseString = null;

try {

// 设置请求头部类型

myPost.setRequestHeader(“Content-Type”, “text/xml”);

myPost.setRequestHeader(“charset”, “iso8859-1”);

// myPost.setRequestHeader(“charset”,”utf-8″);

 

// 设置请求体,即xml文本内容,注:这里写了两种方式,一种是直接获取xml内容字符串,一种是读取xml文件以流的形式

myPost.setRequestBody(xmlFileName);

 

// InputStream body=this.getClass().getResourceAsStream(“/”+xmlFileName);

// myPost.setRequestBody(body);

// myPost.setRequestEntity(new

// StringRequestEntity(xmlString,”text/xml”,”utf-8″));

int statusCode = client.executeMethod(my Post);

if (statusCode == HttpStatus.SC_OK) {

BufferedInputStream bis = new BufferedInputStream(myPost.getResponseBodyAsStream());

byte[] bytes = new byte[1024];

ByteArrayOutputStream bos = new ByteArrayOutputStream();

int count = 0;

while ((count = bis.read(bytes)) != -1) {

bos.write(bytes, 0, count);

}

byte[] strByte = bos.toByteArray();

responseString = new String(strByte, 0, strByte.length, “utf-8”);

// System.out.println(responseString);

bos.close();

bis.close();

}

} catch (Exception e) {

e.printStackTrace();

}

myPost.releaseConnection();

return responseString;

}

 

/**

* @description 将xml字符串转换成map

* @param xml

* @return Map

*/

public static Map readStringXmlOut(String xml) {

Map map = new HashMap();

Document doc = null;

try {

doc = DocumentHelper.parse Text(xml); // 将字符串转为XML

Element rootElt = doc.getRootElement(); // 获取根节点

@SuppressWarnings(“unchecked”)

List list = rootElt.elements();// 获取根节点下所有节点

for (Element element : list) { // 遍历节点

map.put(element.getName(), element.getText()); // 节点的name为map的key,text为map的value

}

} catch (DocumentException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

}

return map;

}

 

// 支付回调验证签名

public static boolean wxPayChack(Map map, String key) throws Exception {

String stringA = “appid=” + map.get(“appid”) + “&attach=” + map.get(“attach”) + “&bank_type=”

+ map.get(“bank_type”) + “&cash_fee=” + map.get(“cash_fee”) + “” + “&fee_type=” + map.get(“fee_type”)

+ “&is_subscribe=” + map.get(“is_subscribe”) + “&mch_id=” + map.get(“mch_id”) + “&nonce_str=”

+ map.get(“nonce_str”) + “&openid=” + map.get(“openid”) + “&out_trade_no=” + map.get(“out_trade_no”)

+ “&result_code=” + map.get(“result_code”) + “&return_code=” + map.get(“return_code”) + “&time_end=”

+ map.get(“time_end”) + “&total_fee=” + map.get(“total_fee”) + “&trade_type=” + map.get(“trade_type”)

+ “&transaction_id=” + map.get(“transaction_id”);

String stringSignTemp = stringA + “&key=” + key;

String stringSignTemp1 = new String(stringSignTemp.getBytes(“iso8859-1”));

String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();

String retSign = (String) map.get(“sign”);

if (retSign.equals(sign)) {

return true;

}

return false;

}

 

// 接收微信回调request 获取xml参数信息

public static Map inputStream2String(HttpServletRequest request) throws Exception {

InputStream is = request.getInputStream();

String xml = WxSignUtil.inputStream2String(is, “utf-8”);

return WxSignUtil.readStringXmlOut(xml);

}

 

/**

* InputStream流转换成String字符串

*

* @param inStream

* InputStream流

* @param encoding

* 编码格式

* @return String字符串

*/

public static String inputStream2String(InputStream inStream, String encoding) {

String result = null;

try {

if (inStream != null) {

ByteArrayOutputStream outStream = new ByteArrayOutputStream();

byte[] tempBytes = new byte[1000];

int count = -1;

while ((count = inStream.read(tempBytes, 0, 1000)) != -1) {

outStream.write(tempBytes, 0, count);

}

tempBytes = null;

outStream.flush();

result = new String(outStream.toByteArray(), encoding);

}

} catch (Exception e) {

result = null;

}

return result;

}

 

// 获取用户的openid

public static String getUserOpenId(Map map) {

String param = “appid=” + map.get(“openappid”) + “&secret=” + map.get(“opensecret”) + “&code=” + map.get(“code”)

+ “&grant_type=authorization_code”;

String ret = HttpUt il.doGet(map.get(“openidurl”), param);

JSONObject jon = JSONObject.parseObject(ret);

String openId = jon.getString(“openid”);

return openId;

}

 

// 微信公众号预下单

public static Map WxH5Md5Sign(Map map, String key) throws Exception {

// //公众账号ID

// String appid=””;

// //商品描述

// String body=””;

// //商户号

// String mch_id=””;

// //随机字符串

// String nonce_str=””;

// //通知地址

// String notify_url=””;

// //用户标识

// String openid=””;

// //商户订单号

// String out_trade_no=””;

// //终端IP

// String spbill_create_ip=””;

// //订单总金额

// int total_fee=0;

// //交易类型

// String trade_type=””;

 

String stringA = “appid=” + map.get(“openappid”) + “&body=” + map.get(“body”) + “&mch_id=”

+ map.get(“openmchid”) + “&nonce_str=” + map.get(“nonce_str”) + “&notify_url=”

+ map.get(“opencallbackurl”) + “&openid=” + map.get(“openid”) + “&out_trade_no =”

+ map.get(“out_trade_no”) + “&spbill_create_ip=127.0.0.1&total_fee=” + map.get(“total_fee”)

+ “&trade_type=JSAPI”;

String stringSignTemp = stringA + “&key=” + key;

// String stringSignTemp1=new String(stringSignTemp.getBytes(“iso8859-1”));

String stringSignTemp1 = new String(stringSignTemp.getBytes(“utf-8”));

String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();

 

String par = “” + “” + “

+ map.get(“openmchid”) + “]]>” + “

+ “” + “

+ “]]>” + “

+ “

+ “” + “

+ map.get(“total_fee”) + “]]>” + “” + “

+ sign + “” + ““;

 

// B8971A5E8220F8B9A1C314FDDA7440C4

String ret = WxSignUtil.post(“https://api.mch.weixin.qq.com/pay/unifiedorder”, par);

Map mapret = readStringXmlOut(ret);

return mapret;

}

 

// 公众号预下单回调验证签名

public static boolean orderPayCallbackChack(Map map, String key) throws Exception {

String stringA = “appid=” + map.get(“appid”) + “&bank_type=” + map.get(“bank_type”) + “&cash_fee=”

+ map.get(“cash_fee”) + “&fee_type=” + map.get(“fee_type”) + “&is_subscribe=” + map.get(“is_subscribe”)

+ “&mch_id=” + map.get(“mch_id”) + “&nonce_str=” + map.get(“nonce_str”) + “&openid=” + map.get(“openid”)

+ “&out_trade_no=” + map.get(“out_trade_no”) + “&result_code=” + map.get(“result_code”)

+ “&return_code=” + map.get(“return_code”) + “&time_en d=” + map.get(“time_end”) + “&total_fee=”

+ map.get(“total_fee”) + “&trade_type=” + map.get(“trade_type”) + “&transaction_id=”

+ map.get(“transaction_id”);

String stringSignTemp = stringA + “&key=” + key;

String stringSignTemp1 = new String(stringSignTemp.getBytes(“utf-8”));

String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();

String retsign = map.get(“sign”) + “”;

if (sign.equals(retsign)) {

return true;

}

return false;

}

 

// 公众号调起支付签名

public static String openSignPayMd5(Map map, String key) throws Exception {

// 公众号id

String appId = “”;

// 时间戳

String timeStamp = “”;

// 随机字符串

String nonceStr = “”;

// 订单详情扩展字符串

String packageout = “”;

// 签名方式

String signType = “”;

 

// String

// stringA=”appid=wx8731a2e298f48739&nonceStr=123456&package=123456&signType=MD5&timeStamp=123456″;

String stringA = “appId=” + m ap.get(“appId”) + “&nonceStr=” + map.get(“nonceStr”) + “&package=”

+ map.get(“package”) + “&signType=” + map.get(“signType”) + “&timeStamp=” + map.get(“timeStamp”);

String stringSignTemp = stringA + “&key=” + key;

// String stringSignTemp1=new String(stringSignTemp.getBytes(“iso8859-1”));

String stringSignTemp1 = new String(stringSignTemp.getBytes(“utf-8”));

String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();

return sign;

}

 

// 微信支付商户退款

public static Map wxPayMachBackToUser(Map map, String key) throws Exception {

 

// //公众账号ID

// String appid=””;

// //商户号

// String mch_id=””;

// //随机字符串

// String nonce_str=””;

// //微信订单号 流水号

// String transaction_id=””;

//// //商户订单号

//// String out_trade_no=””;

// //商户退款单号

// String out_refund_no=””;

// //订单金额 订单总金额,单位为分,只能为整数

// String total_fee=””;

// //退款金额

// String refu nd_fee=””;

// 退款结果通知url

// String notify_url=””;

 

String stringA = “appid=” + map.get(“appid”) + “&mch_id=” + map.get(“mch_id”) + “&nonce_str=”

+ map.get(“nonce_str”) + “&notify_url=” + map.get(“notify_url”) + “&out_refund_no=”

+ map.get(“out_refund_no”) + “&refund_fee=” + map.get(“refund_fee”) + “&total_fee=”

+ map.get(“total_fee”) + “&transaction_id=” + map.get(“transaction_id”);

 

String stringSignTemp = stringA + “&key=” + key;

// String stringSignTemp1=new String(stringSignTemp.getBytes(“iso8859-1”));

String stringSignTemp1 = new String(stringSignTemp.getBytes(“utf-8”));

String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();

 

String par = “” + ” ” + ”

+ map.get(“mch_id”) + “]]>” + ”

+ “]]>” + ”

+ ”

+ ” ” + ”

+ map.get(“total_fee”) + “]]>” + ”

+ “]]>” + ” ” + sign + “” + ““;

 

// String ret=WxSignUtil.post(“https://api.mch.weixin.qq.com/secapi/pay/refund”,

// par);

String ret = WxSignUtil.postData(“https://api.mch.weixin.qq.com/secapi/pay/refund”, par, map.get(“mch_id”) + “”,

map.get(“keyPath”) + “”);

Map mapret = readStringXmlOut(ret);

return mapret;

}

 

// 解密微信退款加密字段

public static Map desDecodeWxPayCallBack(Map map, String key) throws Exception {

// 对商户key做md5,得到32位小写key*

// String mdkey=LogisticsInfoMD5.encode(key).toLowerCase();

SecretKeySpec mdkey = new SecretKeySpec(LogisticsInfoMD5.encode(key).toLowerCase().getBytes(), “AES”);

 

// 微信订单号

String transaction_id = map.get(“transaction_id”);

if (transaction_id != null) {

// 对加密串A做base64解码,得到加密串B

transaction_id = new String(Base64Util.decode(transaction_id));

transaction_id = AESUtil.decryptData(transaction_id, mdkey);

map.put(transaction_id, transaction_id);

}

return map;

}

 

private static int socketTimeout = 10000;// 连接超时时间,默认10秒

private static int connectTimeout = 30000;// 传输超时时间,默认30秒

private static RequestConfig requestConfig;// 请求器的配置

private static CloseableHttpClient httpClient;// HTTP请求器

 

/**

* 通过Https往API post xml数据

*

* @param url

* API地址

* @param xmlObj

* 要提交的XML数据对象

* @param mchId

* 商户ID

* @param certPath

* 证书位置

* @return

*/

public static String postData(String url, String xmlOb j, String mchId, String certPath) {

// 加载证书

try {

initCert(mchId, certPath);

} catch (Exception e) {

e.printStackTrace();

}

String result = null;

HttpPost httpPost = new HttpPost(url);

// 得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别

StringEntity postEntity = new StringEntity(xmlObj, “UTF-8”);

httpPost.addHeader(“Content-Type”, “text/xml”);

httpPost.setEntity(postEntity);

// 根据默认超时限制初始化requestConfig

requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout)

.build();

// 设置请求器的配置

httpPost.setConfig(requestConfig);

try {

HttpResponse response = null;

try {

response = httpClient.execute(httpPost);

} catch (IOException e) {

e.printStackTrace();

}

HttpEntity entity = response.getEntity();

try {

result = EntityUtils.toString(entity, “UTF-8”);

} catch (IOException e) {

e.printStackTrace ();

}

} finally {

httpPost.abort();

}

return result;

}

 

/**

* 加载证书

*

* @param mchId

* 商户ID

* @param certPath

* 证书位置

* @throws Exception

*/

private static void initCert(String mchId, String certPath) throws Exception {

// 证书密码,默认为商户ID

String key = mchId;

// 证书的路径

String path = certPath;

// 指定读取证书格式为PKCS12

KeyStore keyStore = KeyStore.getInstance(“PKCS12”);

// 读取本机存放的PKCS12证书文件

FileInputStream instream = new FileInputStream(new File(path));

try {

// 指定PKCS12的密码(商户ID)

keyStore.load(instream, key.toCharArray());

} finally {

instream.close();

}

SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, key.toCharArray()).build();

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { “TLSv1” }, null,

SSLConnectionSocketFactory.BROWSER_COMPA TIBLE_HOSTNAME_VERIFIER);

httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

}

 

// 微信小程序統一下單

public static Map WxSmallProgramMd5Sign(Map map, String key) throws Exception {

String stringA = “appid=” + map.get(“appid”) + “&attach=” + map.get(“attach”) + “&body=” + map.get(“body”)

+ “&mch_id=” + map.get(“mch_id”) + “&nonce_str=” + map.get(“nonce_str”) + “&notify_url=”

+ map.get(“notify_url”) + “&openid=” + map.get(“openid”) + “&out_trade_no=” + map.get(“out_trade_no”)

+ “&spbill_create_ip=” + map.get(“spbill_create_ip”) + “&total_fee=” + map.get(“total_fee”)

+ “&trade_type=” + map.get(“trade_type”);

 

String stringSignTemp = stringA + “&key=” + key;

String stringSignTemp1 = new String(stringSignTemp.getBytes(“iso8859-1”));

// String stringSignTemp1=new String(stringSignTemp.getBytes(“utf-8”));

String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();

 

Str ing par = “” + “” + map.get(“appid”) + “” + “” + map.get(“attach”) + “

+ “” + map.get(“body”) + “” + “” + map.get(“mch_id”) + “” + “

+ map.get(“nonce_str”) + “” + “” + map.get(“notify_url”) + “

+ “” + map.get(“openid”) + “” + “” + map.get(“out_trade_no”)

+ “” + “” + map.get(“spbill_create_ip”) + “

+ “” + map.get(“total_fee”) + “” + “” + “JSAPI” + “

+ “” + sign + “” + ““;

String ret = WxSignUtil.post(smallprogramorderurl, par);

Map retmap = readStringXmlOut(ret);

return retmap;

}

 

// 微信小程序调起支付签名

public static Map wxSmallProgramPaySign(Map map, String key) throws Exception {

String stringA = “appId=” + map.get(“appid”) + “& nonceStr=” + map.get(“nonceStr”) + “&package=prepay_id=”

+ map.get(“prepay_id”) + “&signType=MD5&timeStamp=” + map.get(“timeStamp”);

 

String stringSignTemp = stringA + “&key=” + key;

String stringSignTemp1 = new String(stringSignTemp.getBytes(“iso8859-1”));

// String stringSignTemp1=new String(stringSignTemp.getBytes(“utf-8”));

String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();

 

Map retmap = new HashMap();

retmap.put(“time”, map.get(“timeStamp”));

retmap.put(“package”, “prepay_id=” + map.get(“prepay_id”));

retmap.put(“paySign”, sign);

retmap.put(“signType”, “MD5”);

retmap.put(“nonceStr”, map.get(“nonceStr”));

return retmap;

}

 

// 微信小程序获得openid

public static String wxSmallProgramGetOpenId(Map map, String secret) throws Exception {

String getUrl = “https://api.weixin.qq.com/sns/jscode2session”;

String param = “appid=” + map.get(“appid”) + “&secret= ” + secret + “&js_code=” + map.get(“code”)

+ “&grant_type=authorization_code”;

String ret = HttpUtil.doGet(getUrl, param);

// {“session_key”:”vz5yE67kF3p8CKpTtLgobw==”,”openid”:”oMEFK5M53RmMPTow1_GoBRKkrOI4″}

JSONObject json = JSONObject.parseObject(ret);

String openid = json.getString(“openid”);

String session_key = json.getString(“session_key”);

return openid + “,” + session_key;

}

 

// 查询微信订单

public static void queryOrderPayInfo() throws Exception {

String stringA = “appid=wx608bbf2ae0956623&mch_id=1512285851&nonce_str=456168546545&out_trade_no=0a3f639a3f174529a7ca236632f36d4d&key=9dffe0f7a65bb1976d4b33d7a8b1f7ac”;

String stringSignTemp = stringA;

String stringSignTemp1 = new String(stringSignTemp.getBytes(“utf-8”));

String sign = LogisticsInfoMD5.encode(stringSignTemp1).toUpperCase();

 

String par = “” + “

+ “” + “

+ “” + “” + sign

+ “” + ““;

String ret = WxSignUtil.post(“https://api.mch.weixin.qq.com/pay/orderquery”, par);

Map mapret = readStringXmlOut(ret);

System.out.println(mapret);

}

 

}

 

 

pom.xml:

 

 

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>

4.0.0

 

isweb

ccunix.is

0.0.1-SNAPSHOT

war

 

 

 

4.0.2.RELEASE

3.2 .8

1.7.12

1.2.17

junit

junit

3.8.1

test

javax

javaee-api

provided

7.0

org.springframework

spring-test

${srping.version}

org.springframework

spring-core

${srping.version}

com.google.zxing

javase

3.3.3

 

org.apache.httpcomponents

httpclient

 

org.springframework

spring-oxm

${srping.version}

org.springframework

spring-tx

${srping.version}

org.springframework

spring-jdbc

${srping.version}

org.springframework

spring-aop

${srping.version}

org.springframework

spring-context< /p>

${srping.version}

org.springframework

spring-context-support

${srping.version}

org.springframework

spring-expression

${srping.version}

org.springframework

spring-orm

${srping.version}

org.springframework

spring-web

${srping.version}

org.springframework

spring-webmvc

${srping.version}

org.mybatis

mybatis

${mybatis.version}

org.mybatis

mybatis-spring

1.2.2

 

mysql

mysql-connector-java

5.1.35

commons-dbcp

commons-dbcp

1.4

jstl

jstl

1.2

 

com.belerweb

pinyin4j

2.5.0

 

log4j

log4j

${log4j.version}

org.slf4j

slf4j-api

${slf4j.version}

org.slf4j

slf4j-log4j12

${slf4j.version}

 

com.alibaba

fastjson

1.2.6

org.codehaus.jackson

jackson-mapper-asl

1.9.13

 

com .fasterxml.jackson.core

jackson-databind

2.4.2

 

 

commons-fileupload

commons-fileupload

1.3.1

commons-io

commons-io

2.4

commons-codec

commons-codec

1.10

org.aspectj

aspectjweaver

1.6.12

org.springframework.data

spring-data-redis

1.0.2.RELEASE

org.springframework

spring-test

3.1.2.RELEASE

test

redis.clients

jedis

2.1.0

 

 

org.eclipse.paho

org.eclipse.paho.client.mqttv3

1.2.0

commons-codec

commons-codec

1.10

 

org.json

json

20090211

 

org.apache.httpcomponents

httpclient

4.3.5

 

 

org.apache.poi

poi

3.9

org.apache.poi

poi-ooxml

3.9

 

 

 

org.hibernate

hibernate-validator

5.3.0.Alpha1

org.slf4j

slf4j-api

1.7.21

 

org.slf4j

slf4j-log4j12

1.7.21

org.bouncycastle

bcprov-jdk15on

1.55

commons-codec

commons-codec

1.10

 

dom4j

dom4j

1.6.1

 

com.baidu.aip

java-sdk

4.8.0

 

 

 

org.apache.maven.plugins

maven-compiler-plugin

1.7

1.7

 

org.apache.maven.plugins

m aven-war-plugin

3.0.0

 

maven_project

 

 

 

 

 

 

点击支付页面:demo.jsp

 

<%@ page language="java" contentType="text/html; charset=UTF-8"

pageEncoding=”UTF-8″%>

<%@include file="/WEB-INF/html/base/baseurl.jsp"%>

Insert title here

微信支付

 

 

 

 

 

生成二维码页面:qrcode.jsp

 

 

<%@ page language="java" contentType="text/html; charset=UTF-8"

pageEncoding=”UTF-8″%>

<%@include file="/WEB-INF/html/base/baseurl.jsp"%>

Javascript 二维码生成库:QRCode

<%

out.print(“<%=request.getAttribute("param") %><% out.print("\"");

%>

content=”width=device-width,initial-scale=1,user-scalable=no” />

 

 

 

注意:appid需要跟商户号绑定

Leave a Comment

Your email address will not be published.