1.获得openid
~~~
@WebServlet("/GetOpenIdServlet")
public class GetOpenIdServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String APPID = "";
private static final String APPSECRET = "";
private static final String oauth_connect_token_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=URL&response_type=code&scope=snsapi_base&state=123#wechat_redirect";
private static final String oauth_access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String code = request.getParameter("code");
if(code==null ||code.length()==0)
{
//1. 获得code
StringBuffer url = request.getRequestURL();
String codeRequestUrl = oauth_connect_token_url.replace("APPID", APPID).replace("URL", url);
response.sendRedirect(codeRequestUrl);
}
else
{
System.out.println("================================="+code);
//2. 获得openid
String requestUrl = oauth_access_token_url.replace("APPID", APPID).replace("SECRET", APPSECRET).replace("CODE", code);
System.out.println("requestUrl:"+requestUrl);
JSONObject jsonCode = httpsRequest(requestUrl,"GET");
String openid="";
if (jsonCode != null && !"".equals(jsonCode)) {
openid = jsonCode.getString("openid");
}
System.out.println("==============openId=========================" + openid);
request.setAttribute("openid", openid);
request.getRequestDispatcher("/pay.jsp").forward(request, response);
}
}
}
~~~
2. pay.jsp发起支付
~~~
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
<script type="text/javascript" src="js/jquery-3.2.1.js"></script>
<script type="text/javascript">
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
$(function(){
$("#btn_pay").click(function(){
$.post('<%=basePath%>/PayServlet', {
openid: $("#openid").val(),
nname: "feiyy",
phone: "15940471397"
},//新版支付(便利店+商场共用)
function (data) {
if (data) {
data = JSON.parse(data);
//微信支付
if (data.result == "true") {
WeixinJSBridge.invoke('getBrandWCPayRequest', {
"appId": data.appId, //公众号名称,由商户传入
"timeStamp": data.timeStamp, //时间戳,自1970年以来的秒数
"nonceStr": data.nonceStr, //随机串
"package": data.package,
"signType": data.signType, //微信签名方式:
"paySign": data.paySign //微信签名
}, function (res) {
alert(res.err_msg);
alert(JSON.stringify(res));
if (res.err_msg == "get_brand_wcpay_request:ok") {
window.location.href="payResult.html";
} else if (res.err_msg == "get_brand_wcpay_request:cancel") {
alert("用户取消支付!");
} else {
alert("支付失败!");
}
});
}
else {
alert("支付失败");
}
}
})
});
})
</script>
</head>
<body>
<input type="hidden" value="<%=request.getAttribute("openid") %>" id="openid"/>
<input id="btn_pay" type="button" value="支付 "/>
</body>
</html>
~~~
PayServlet
~~~
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.eclipse.jdt.internal.compiler.batch.Main;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import net.sf.json.JSONObject;
@WebServlet("/PayServlet")
public class PayServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String appid= "";
private static final String appsecret= "";
private static final String partner="";
private static final String partnerkey = "";
public static DefaultHttpClient httpclient;
static
{
httpclient = new DefaultHttpClient();
httpclient = (DefaultHttpClient)HttpClientConnectionManager.getSSLInstance(httpclient);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 获得openid
String openid = request.getParameter("openid");
System.out.println("PayServlet==="+openid);
//2. 获得nonceStr
String nonceStr = this.getNonceStr();
String finalpackage= this.getPackage(openid,nonceStr,request);
finalpackage= "{\"result\":\"true\","+finalpackage+"}";
System.out.println(finalpackage);
response.setContentType("text/plain");
PrintWriter out = response.getWriter();
out.write(finalpackage);
out.flush();
//5. ajax影响 {result:"", package:"", paySign:""}
}
public String createSign(SortedMap<String, String> packageParams) {
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=" + partnerkey);
System.out.println("sign-------------------加密前:"+sb.toString());
String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8")
.toUpperCase();
System.out.println("sign-------------------加密后:"+sign);
return sign;
}
public String getPayNo(String url,String xmlParam){
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
HttpPost httpost= HttpClientConnectionManager.getPostMethod(url);
String prepay_id = "";
try {
httpost.setEntity(new StringEntity(xmlParam, "UTF-8"));
HttpResponse response = httpclient.execute(httpost);
String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println("weixin fanhui preid:"+jsonStr);
if(jsonStr.indexOf("FAIL")!=-1){
return prepay_id;
}
Map map = doXMLParse(jsonStr);
prepay_id = (String) map.get("prepay_id");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return prepay_id;
}
public static Map doXMLParse(String strxml) throws Exception {
if(null == strxml || "".equals(strxml)) {
return null;
}
Map m = new HashMap();
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(new ByteArrayInputStream(strxml.getBytes()));
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 = getChildrenText(children);
}
m.put(k, v);
}
//关闭流
return m;
}
/**
* 获取子结点的xml
* @param children
* @return String
*/
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if(!children.isEmpty()) {
Iterator it = children.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if(!list.isEmpty()) {
sb.append(getChildrenText(list));
}
sb.append(value);
sb.append("</" + name + ">");
}
}
return sb.toString();
}
public String getNonceStr() {
// 随机数
String currTime = this.getCurrTime();
// 8位日期
String strTime = currTime.substring(8, currTime.length());
// 四位随机数
String strRandom = this.buildRandom(4) + "";
// 10位序列号,可以自行调整。
return strTime + strRandom;
}
public String getCurrTime() {
Date now = new Date();
SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");
String s = outFormat.format(now);
return s;
}
public int buildRandom(int length) {
int num = 1;
double random = Math.random();
if (random < 0.1) {
random = random + 0.1;
}
for (int i = 0; i < length; i++) {
num = num * 10;
}
return (int) ((random * num));
}
private String getPackage(String openId, String nonce_str,HttpServletRequest request)
{
SortedMap<String, String> packageParams = new TreeMap<String, String>();
String mch_id = partner;
String body = "测试订单";
String out_trade_no = UUID.randomUUID().toString().replace("-", "");
String attach = "feiyy,15940471397";
String totalFee = "1";
String spbill_create_ip = "127.0.0.1";
//String path = request.getContextPath();
//String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
//String notify_url = basePath+"/NotifyServlet";
String notify_url = "http://www.zyrc.tech/TestWeixinPay/NotifyServlet";
String trade_type = "JSAPI";
packageParams.put("appid", appid);
packageParams.put("mch_id", mch_id);
packageParams.put("nonce_str", nonce_str);
packageParams.put("body", body);
packageParams.put("out_trade_no", out_trade_no);
packageParams.put("attach", "feiyy,15940471397");
// 这里写的金额为1 分到时修改
packageParams.put("total_fee", totalFee);
packageParams.put("spbill_create_ip", spbill_create_ip);
packageParams.put("notify_url", notify_url);
packageParams.put("trade_type", trade_type);
packageParams.put("openid", openId);
String sign = this.createSign(packageParams);
String xml = "<xml>" +
"<appid>" + appid + "</appid>" +
"<mch_id>"+ mch_id + "</mch_id>" +
"<nonce_str>" + nonce_str + "</nonce_str>" +
"<sign>" + sign + "</sign>"+
"<body><![CDATA[" + body + "]]></body>" +
"<out_trade_no>" + out_trade_no+ "</out_trade_no>" +
"<attach>" + attach + "</attach>"+
"<total_fee>" + totalFee + "</total_fee>"+
"<spbill_create_ip>" + spbill_create_ip+ "</spbill_create_ip>"+
"<notify_url>" + notify_url+ "</notify_url>" +
"<trade_type>" + trade_type+ "</trade_type>" +
"<openid>" + openId + "</openid>"+
"</xml>";
System.out.println("xml======"+xml);
String prepay_id = "";
String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
prepay_id = this.getPayNo(createOrderURL, xml);
System.out.println("商城获取到的预支付ID:" + prepay_id);
//获取prepay_id后,拼接最后请求支付所需要的package
SortedMap<String, String> finalpackage = new TreeMap<String, String>();
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String packages = "prepay_id="+prepay_id;
finalpackage.put("appId", appid);
finalpackage.put("timeStamp", timestamp);
finalpackage.put("nonceStr", nonce_str);
finalpackage.put("package", packages);
finalpackage.put("signType", "MD5");
//要签名
String finalsign = this.createSign(finalpackage);
String finaPackage = "\"appId\":\"" + appid + "\",\"timeStamp\":\"" + timestamp
+ "\",\"nonceStr\":\"" + nonce_str + "\",\"package\":\""
+ packages + "\",\"signType\":\"MD5" + "\",\"paySign\":\""
+ finalsign + "\"";
System.out.println("V3 jsApi package:"+finaPackage);
return finaPackage;
}
}
~~~
HttpClientConnectionManager
~~~
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.client.DefaultHttpClient;
public class HttpClientConnectionManager {
/**
* 获取SSL验证的HttpClient
* @param httpClient
* @return
*/
public static HttpClient getSSLInstance(HttpClient httpClient){
ClientConnectionManager ccm = httpClient.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", MySSLSocketFactory.getInstance(), 443));
httpClient = new DefaultHttpClient(ccm, httpClient.getParams());
return httpClient;
}
/**
* 模拟浏览器post提交
*
* @param url
* @return
*/
public static HttpPost getPostMethod(String url) {
HttpPost pmethod = new HttpPost(url); // 设置响应头信息
pmethod.addHeader("Connection", "keep-alive");
pmethod.addHeader("Accept", "*/*");
pmethod.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
pmethod.addHeader("Host", "api.mch.weixin.qq.com");
pmethod.addHeader("X-Requested-With", "XMLHttpRequest");
pmethod.addHeader("Cache-Control", "max-age=0");
pmethod.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
return pmethod;
}
/**
* 模拟浏览器GET提交
* @param url
* @return
*/
public static HttpGet getGetMethod(String url) {
HttpGet pmethod = new HttpGet(url);
// 设置响应头信息
pmethod.addHeader("Connection", "keep-alive");
pmethod.addHeader("Cache-Control", "max-age=0");
pmethod.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
pmethod.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/;q=0.8");
return pmethod;
}
}
~~~
MySSLSocketFactory
~~~
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import org.apache.http.conn.ssl.SSLSocketFactory;
public class MySSLSocketFactory extends SSLSocketFactory{
static{
mySSLSocketFactory = new MySSLSocketFactory(createSContext());
}
private static MySSLSocketFactory mySSLSocketFactory = null;
private static SSLContext createSContext(){
SSLContext sslcontext = null;
try {
sslcontext = SSLContext.getInstance("SSL");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
try {
sslcontext.init(null, new TrustManager[]{new TrustAnyTrustManager()}, null);
} catch (KeyManagementException e) {
e.printStackTrace();
return null;
}
return sslcontext;
}
private MySSLSocketFactory(SSLContext sslContext) {
super(sslContext);
this.setHostnameVerifier(ALLOW_ALL_HOSTNAME_VERIFIER);
}
public static MySSLSocketFactory getInstance(){
if(mySSLSocketFactory != null){
return mySSLSocketFactory;
}else{
return mySSLSocketFactory = new MySSLSocketFactory(createSContext());
}
}
}
~~~
MyX509TrustManager
~~~
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* 证书信任管理器(用于https请求)
*
* @author 捷微团队
* @date 2013-08-08
*/
public class MyX509TrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
~~~
TrustAnyTrustManager
~~~
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
*
* @author Administrator
*
*/
public class TrustAnyTrustManager implements X509TrustManager{
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
~~~
MD5Util
~~~
import java.security.MessageDigest;
public class MD5Util {
private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++)
resultSb.append(byteToHexString(b[i]));
return resultSb.toString();
}
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n += 256;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
public static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString
.getBytes()));
else
resultString = byteArrayToHexString(md.digest(resultString
.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString;
}
private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
}
~~~