微信支付

微信支付首先要登陆到微信官网注册账号,详细说明见官方文档

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" };
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值