微信支付首先要登陆到微信官网注册账号,详细说明见官方文档
https://mp.weixin.qq.com/wiki
查看文档结合代码事半功倍哦。
1.前台js执行支付js
<script type="text/javascript">
function callpay()
{
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener('WeixinJSBridgeReady', onBridgeReady,
false);
} else if (document.attachEvent) {
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
} else {
onBridgeReady();
}
}
function onBridgeReady(){
$.ajax({
url: "<c:url value='/wechat/OrderPay' />",
data: {"orderID": "${oh.OrderID}" },
type: "POST",
datatype: "json"
}).done(function (data) {
if (data.result=="success") {
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
{
"appId" : data.appId, //公众号名称,由商户传入
"timeStamp" : data.timeStamp,//时间戳,自1970年以来的秒数
"nonceStr" : data.nonceStr, //随机串
"package" : data.packageStr,
"signType" : data.signType,//微信签名方式:
"paySign" : data.paySign //微信签名
},
function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
alert("支付成功");
} else {
alert(res.err_msg);
}
});
} else {
alert("创建订单失败");
}
}).fail(function (error) {
console.log(error);
});
}
</script>
2.付款成功页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE html>
<html>
<head>
<base href="<%=basePath%>">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>pay result - ZipX</title>
<jsp:include page="top.jsp"></jsp:include>
</head>
<body>
<div class="container-full">
success
</div>
</body>
</html>
====================后台=============================
/**
* 订单支付
* @param orderID
*/
@RequestMapping(value="/OrderPay",method=RequestMethod.POST,produces="application/json;charset=UTF-8")
@ResponseBody
public Map<String, String> OrderPay(@RequestParam("orderID") Integer orderID,
HttpServletRequest request,
HttpServletResponse response,
HttpSession session){
Map<String, String> data =new HashMap<String, String>();
try {
String openId = (String) session.getAttribute(Const.SESSION_WEIXIN_OPENID);
String noncestr = Sha1Util.getNonceStr();
// 生成1970年到现在的秒数.
String timestamp = Sha1Util.getTimeStamp();
// 订单号,自定义生成规则
String out_trade_no = orderID.toString();
// 订单金额,应该是根据state(商品id)从数据库中查询出来
String order_price = String.valueOf(1);
// 商品描述,应该是根据state(商品id)从数据库中查询出来
String body = "商品描述,测试....";
RequestHandler reqHandler = new RequestHandler(request, response);
//初始化
reqHandler.init();
//微信分配的公众账号ID(企业号corpid即为此appId)
reqHandler.setParameter("appid", WxPayConfig.APP_ID);
// 微信支付分配的商户号
reqHandler.setParameter("mch_id", WxPayConfig.MCH_ID);
// 终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传"WEB"
reqHandler.setParameter("device_info", "WEB");
// 随机字符串,不长于32位。推荐随机数生成算法
reqHandler.setParameter("nonce_str", noncestr);
// 商品描述
reqHandler.setParameter("body", body);
// 商家订单号
reqHandler.setParameter("out_trade_no", out_trade_no);
// 商品金额,以分为单位
reqHandler.setParameter("total_fee", order_price);
// APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。
reqHandler.setParameter("spbill_create_ip",PublicUtil.getRemoteHost(request));
// 下面的notify_url是用户支付成功后为微信调用的action 异步回调.
reqHandler.setParameter("notify_url", WxPayConfig.NOTIFY_URL);
// 交易类型,取值如下:JSAPI,NATIVE,APP,详细说明见参数规定
reqHandler.setParameter("trade_type", "JSAPI");
// ------------需要进行用户授权获取用户openid-------------
reqHandler.setParameter("openid", openId); // 这个必填.
// 生成签名,并且转为xml
String requestXml = reqHandler.getRequestXml();
// 得到的预支付id
String prepay_id = WechatPayUtil.unifiedorder(requestXml);
SortedMap<String, String> params = new TreeMap<String, String>();
params.put("appId", WxPayConfig.APP_ID);
params.put("timeStamp", timestamp);
params.put("nonceStr", noncestr);
params.put("package", "prepay_id=" + prepay_id);
params.put("signType", "MD5");
// 生成支付签名,这个签名 给 微信支付的调用使用
SortedMap<Object,Object> signMap = new TreeMap<Object,Object>();
signMap.put("appId", WxPayConfig.APP_ID);
signMap.put("timeStamp", timestamp);
signMap.put("nonceStr", noncestr);
signMap.put("package", "prepay_id=" + prepay_id);
signMap.put("signType", "MD5");
// 微信支付签名
String paySign = MD5Util.createSign(signMap, WxPayConfig.KEY);
//微信分配的公众账号ID(企业号corpid即为此appId)
data.put("appId", WxPayConfig.APP_ID);
// 时间戳
data.put("timeStamp", timestamp);
// 随机字符串
data.put("nonceStr", noncestr);
// 预支付id
data.put("packageStr", "prepay_id=" + prepay_id);
// 加密格式
data.put("signType", WxPayConfig.SIGN_TYPE);
// 微信支付签名
data.put("paySign", paySign);
data.put("result", "success");
} catch (Exception e) {
logger.error(e.toString());
data.put("result", "error");
}
return data;
}
支付回掉
@RequestMapping("/OrderPayReturn")
public String notify(HttpServletRequest request, HttpServletResponse response) {
try {
LogUtil.write("enter notify");
InputStream inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
outSteam.close();
inStream.close();
String resultStr = new String(outSteam.toByteArray(), WxPayConfig.CHARTSET);
Map<String, String> resultMap = XMLUtil.doXMLParse(resultStr);
LogUtil.write("wechat return map:" + resultMap.toString());
String appid = resultMap.get("appid");
String bank_type = resultMap.get("bank_type");
String cash_fee = resultMap.get("cash_fee");
String fee_type = resultMap.get("fee_type");
String is_subscribe = resultMap.get("is_subscribe");
String mch_id = resultMap.get("mch_id");
String nonce_str = resultMap.get("nonce_str");
String openid = resultMap.get("openid");
String out_trade_no = resultMap.get("out_trade_no");
String result_code = resultMap.get("result_code");
String return_code = resultMap.get("return_code");
String sign = resultMap.get("sign");
String time_end = resultMap.get("time_end");
String total_fee = resultMap.get("total_fee");
String trade_type = resultMap.get("trade_type");
String transaction_id = resultMap.get("transaction_id");
LogUtil.write("openid:" + openid);
LogUtil.write("sign:" + sign);
LogUtil.write("out_trade_no:" + out_trade_no);//商户订单号
LogUtil.write("transaction_id:" + transaction_id);//交易号
SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
parameters.put("appid", appid);
parameters.put("bank_type", bank_type);
parameters.put("cash_fee", cash_fee);
parameters.put("fee_type", fee_type);
parameters.put("is_subscribe", is_subscribe);
parameters.put("mch_id", mch_id);
parameters.put("nonce_str", nonce_str);
parameters.put("openid", openid);
parameters.put("out_trade_no", out_trade_no);
parameters.put("result_code", result_code);
parameters.put("return_code", return_code);
parameters.put("time_end", time_end);
parameters.put("total_fee", total_fee);
parameters.put("trade_type", trade_type);
parameters.put("transaction_id", transaction_id);
String signature = MD5Util.createSign(parameters,WxPayConfig.KEY);
LogUtil.write("my signature:" + signature);
LogUtil.write("wechat return signature:" + sign);
if(!signature.equals(sign)){
throw new Exception("The signature does not agree.");
}
if (!result_code.equals("SUCCESS")) {
throw new Exception("WeChat returned transaction status is not correct.");
}
OrderHeader order = orderService.findOrderByOrderID(Integer.valueOf(out_trade_no));
if(order == null){
throw new Exception("Didn't find the corresponding order number.");
}
response.getWriter().write(RequestHandler.setXML("SUCCESS", ""));
} catch (UnsupportedEncodingException e) {
logger.error(e.toString());
} catch (IOException e) {
logger.error(e.toString());
} catch (JDOMException e) {
logger.error(e.toString());
} catch (Exception e) {
logger.error(e.toString());
}
return "weixin/OrderPayReturn";
}
=====================================
package com.zipx.util.wechat;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RequestHandler {
private String gateUrl;
private String key;
private SortedMap parameters;
private String debugInfo;
protected HttpServletRequest request;
protected HttpServletResponse response;
public RequestHandler(HttpServletRequest request, HttpServletResponse response) {
this.request = request;
this.response = response;
this.gateUrl = "https://gw.tenpay.com/gateway/pay.htm";
this.key = "";
this.parameters = new TreeMap();
this.debugInfo = "";
}
public void init() {
//nothing to do
}
public String getGateUrl() {
return gateUrl;
}
public void setGateUrl(String gateUrl) {
this.gateUrl = gateUrl;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getParameter(String parameter) {
String s = (String)this.parameters.get(parameter);
return (null == s) ? "" : s;
}
public void setParameter(String parameter, String parameterValue) {
String v = "";
if(null != parameterValue) {
v = parameterValue.trim();
}
this.parameters.put(parameter, v);
}
public SortedMap getAllParameters() {
return this.parameters;
}
public String getDebugInfo() {
return debugInfo;
}
public String getRequestURL() throws UnsupportedEncodingException {
this.createSign();
StringBuffer sb = new StringBuffer();
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(!"spbill_create_ip".equals(k)) {
sb.append(k + "=" + URLEncoder.encode(v, WxPayConfig.CHARTSET) + "&");
} else {
sb.append(k + "=" + v.replace("\\.", "%2E") + "&");
}
}
String reqPars = sb.substring(0, sb.lastIndexOf("&"));
//
return this.getGateUrl() + "?" + reqPars;
}
public void doSend() throws UnsupportedEncodingException, IOException {
this.response.sendRedirect(this.getRequestURL());
}
protected void createSign() {
StringBuffer sb = new StringBuffer();
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + WxPayConfig.KEY);
String sign = MD5Util.MD5Encode(sb.toString(), WxPayConfig.CHARTSET).toUpperCase();
this.setParameter("sign", sign);
//debug
this.setDebugInfo(sb.toString() + " => sign:" + sign);
}
protected void setDebugInfo(String debugInfo) {
this.debugInfo = debugInfo;
}
protected HttpServletRequest getHttpServletRequest() {
return this.request;
}
protected HttpServletResponse getHttpServletResponse() {
return this.response;
}
/**
* @param return_code
* @param return_msg
* @return
*/
public static String setXML(String return_code, String return_msg) {
return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg
+ "]]></return_msg></xml>";
}
/**
* @return
* @throws UnsupportedEncodingException
*/
public String getRequestXml() throws UnsupportedEncodingException {
this.createSign();
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
} else {
sb.append("<" + k + ">" + v + "</" + k + ">");
}
}
sb.append("</xml>");
return sb.toString();
}
}
=============================
package com.zipx.util.wechat;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RequestHandler {
private String gateUrl;
private String key;
private SortedMap parameters;
private String debugInfo;
protected HttpServletRequest request;
protected HttpServletResponse response;
public RequestHandler(HttpServletRequest request, HttpServletResponse response) {
this.request = request;
this.response = response;
this.gateUrl = "https://gw.tenpay.com/gateway/pay.htm";
this.key = "";
this.parameters = new TreeMap();
this.debugInfo = "";
}
public void init() {
//nothing to do
}
public String getGateUrl() {
return gateUrl;
}
public void setGateUrl(String gateUrl) {
this.gateUrl = gateUrl;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getParameter(String parameter) {
String s = (String)this.parameters.get(parameter);
return (null == s) ? "" : s;
}
public void setParameter(String parameter, String parameterValue) {
String v = "";
if(null != parameterValue) {
v = parameterValue.trim();
}
this.parameters.put(parameter, v);
}
public SortedMap getAllParameters() {
return this.parameters;
}
public String getDebugInfo() {
return debugInfo;
}
public String getRequestURL() throws UnsupportedEncodingException {
this.createSign();
StringBuffer sb = new StringBuffer();
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(!"spbill_create_ip".equals(k)) {
sb.append(k + "=" + URLEncoder.encode(v, WxPayConfig.CHARTSET) + "&");
} else {
sb.append(k + "=" + v.replace("\\.", "%2E") + "&");
}
}
String reqPars = sb.substring(0, sb.lastIndexOf("&"));
//
return this.getGateUrl() + "?" + reqPars;
}
public void doSend() throws UnsupportedEncodingException, IOException {
this.response.sendRedirect(this.getRequestURL());
}
protected void createSign() {
StringBuffer sb = new StringBuffer();
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
String v = (String)entry.getValue();
if(null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + WxPayConfig.KEY);
String sign = MD5Util.MD5Encode(sb.toString(), WxPayConfig.CHARTSET).toUpperCase();
this.setParameter("sign", sign);
//debug
this.setDebugInfo(sb.toString() + " => sign:" + sign);
}
protected void setDebugInfo(String debugInfo) {
this.debugInfo = debugInfo;
}
protected HttpServletRequest getHttpServletRequest() {
return this.request;
}
protected HttpServletResponse getHttpServletResponse() {
return this.response;
}
/**
* @param return_code
* @param return_msg
* @return
*/
public static String setXML(String return_code, String return_msg) {
return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg
+ "]]></return_msg></xml>";
}
/**
* @return
* @throws UnsupportedEncodingException
*/
public String getRequestXml() throws UnsupportedEncodingException {
this.createSign();
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
Set es = this.parameters.entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
} else {
sb.append("<" + k + ">" + v + "</" + k + ">");
}
}
sb.append("</xml>");
return sb.toString();
}
}
package com.zipx.util.wechat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
public class WechatPayUtil {
/**
* 统一下单接口
* 参考文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
* @return
* @throws Exception
*/
public static String unifiedorder(String requestXml) throws Exception{
// 统一下单接口提交 xml格式
URL orderUrl = new URL("https://api.mch.weixin.qq.com/pay/unifiedorder");
HttpURLConnection conn = (HttpURLConnection) orderUrl.openConnection();
conn.setConnectTimeout(30000); // 设置连接主机超时(单位:毫秒)
conn.setReadTimeout(30000); // 设置从主机读取数据超时(单位:毫秒)
conn.setDoOutput(true); // post请求参数要放在http正文内,顾设置成true,默认是false
conn.setDoInput(true); // 设置是否从httpUrlConnection读入,默认情况下是true
conn.setUseCaches(false); // Post 请求不能使用缓存
// 设定传送的内容类型是可序列化的java对象(如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestMethod("POST");// 设定请求的方法为"POST",默认是GET
conn.setRequestProperty("Content-Length", requestXml.length() + "");
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), WxPayConfig.CHARTSET);
out.write(requestXml.toString());
out.flush();
out.close();
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
return null;
}
// 获取响应内容体
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), WxPayConfig.CHARTSET));
String line = "";
StringBuffer strBuf = new StringBuffer();
while ((line = in.readLine()) != null) {
strBuf.append(line).append("\n");
}
in.close();
System.out.println("result=========返回的xml=============" + strBuf.toString());
Map<String, String> orderMap = XMLUtil.doXMLParse(strBuf.toString());
System.out.println("orderMap===========================" + orderMap);
// 获取
String prepay_id = orderMap.get("prepay_id");
return prepay_id;
}
}
============================
package com.zipx.util.wechat;
import java.security.MessageDigest;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
public class MD5Util {
@SuppressWarnings("rawtypes")
public static String createSign(SortedMap<Object, Object> parameters, String key) {
StringBuffer sb = new StringBuffer();
Set es = parameters.entrySet();// 所有参与传参的参数按照accsii排序(升序)
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
Object v = entry.getValue();
if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + key);
String sign = MD5Util.MD5Encode(sb.toString(), WxPayConfig.CHARTSET).toUpperCase();
return sign;
}
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" };
}