目录
使用须知:
需先在微信中开通支付宝H5支付,开通细节暂不描述。。
一:maven
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
二:java代码
package com.vrv.Govern.controller.Wx;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.vrv.Govern.util.DateUtils;
import com.vrv.Govern.util.PrintWriterUtils;
import com.vrv.Govern.util.ResultEntitylayui;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/Home_WxPay")
public class Home_WxPayController {
/**
* Created By Mengkai
* 微信发起回调页面
*
* @return
*/
@RequestMapping("/index")
public String index() {
return "Wx/index";
}
/**
* Created By Mengkai
* 支付成功回调页面
*
* @return
*/
@RequestMapping(value = "succ", produces = "application/json;charset=utf-8")
@ResponseBody
public String succ() {
return "Wx/succ";
}
/**
* Created By Mengkai
* 发起支付方法
*
* @param response
* @param request
*/
@RequestMapping(value = "pay", produces = "application/json;charset=utf-8")
@ResponseBody
public void pay(HttpServletResponse response, HttpServletRequest request) {
Gson gson = new GsonBuilder().serializeNulls().setDateFormat(DateUtils.DateFormat4).create();
ResultEntitylayui mResultEntity = new ResultEntitylayui();
try {
long time = System.currentTimeMillis();
XCFWXPayConfig xcfwxPayConfig = new XCFWXPayConfig(request);
WXPay wxPay = new WXPay(xcfwxPayConfig);
String spbill_create_ip = request.getParameter("ip");
Map<String, String> map = new HashMap<>();
map.put("nonce_str", WXPayUtil.generateNonceStr());
map.put("body", "缴纳");
map.put("out_trade_no", "Dj" + time);
map.put("total_fee", "1");
map.put("spbill_create_ip", spbill_create_ip);
map.put("notify_url", "http://cs/cs/css/payNotify.active");
map.put("trade_type", "MWEB");
Map<String, String> res = wxPay.unifiedOrder(map);
//拼接链接
String mweb_url = "";
if (res.containsKey("mweb_url")) {
String redirectUrl = "http://cs/cs/cs/succ.active";
mweb_url = res.get("mweb_url") + "&redirect_url=" + URLEncoder.encode(redirectUrl, "GBK");
}
//返回链接,为前台提供跳转mweb_url,唤起微信
mResultEntity.setData(mweb_url);
PrintWriterUtils.printWriter(response, gson.toJson(mResultEntity));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Created By Mengkai
* 处理回调
*
* @param request
* @param response
*/
@RequestMapping(value = "payNotify", produces = "application/json;charset=utf-8")
@ResponseBody
public synchronized void payNotify(HttpServletRequest request, HttpServletResponse response) {
System.out.println("进入回调");
try {
String resXml = "";
XCFWXPayConfig xcfwxPayConfig = new XCFWXPayConfig(request);
WXPay wxPay = new WXPay(xcfwxPayConfig);
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 result = new String(outSteam.toByteArray(), "utf-8");// 获取微信调用我们notify_url的返回信息
Map<String, String> map = WXPayUtil.xmlToMap(result); //微信回调后详细参数
if (wxPay.isPayResultNotifySignatureValid(map)) {
//TODO::业务处理开始
System.out.println("业务处理开始");
//订单入库
//TODO::业务处理结束
}
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(resXml.getBytes());
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
特别说明:
这两个工具类是调用及返回json数据的工具类,在使用时可换为自己使用的方式调用
此工具类为实体类,用于封装数据,使用时也可换为自己使用的方式,内容示例,
回调地址:
这两项需更换,其他页面跳转自行调整
工具类
package com.vrv.Govern.controller.Wx;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
/**
* Http客户端工具类<br/>
* 这是内部调用类,请不要在外部调用。
*
* @author miklchen
*
*/
public class HttpUtil {
private final static int CONNECT_TIMEOUT = 5000; // in milliseconds
private final static String DEFAULT_ENCODING = "UTF-8";
public static String postData(String urlStr, String data) {
return postData(urlStr, data, null);
}
public static String postData(String urlStr, String data, String contentType) {
BufferedReader reader = null;
try {
URL url = new URL(urlStr);
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
conn.setConnectTimeout(CONNECT_TIMEOUT);
conn.setReadTimeout(CONNECT_TIMEOUT);
if (contentType != null)
conn.setRequestProperty("content-type", contentType);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);
if (data == null)
data = "";
writer.write(data);
writer.flush();
writer.close();
reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append("\r\n");
}
return sb.toString();
} catch (IOException e) {
} finally {
try {
if (reader != null)
reader.close();
} catch (IOException e) {
}
}
return null;
}
/**
* 获取真实ip地址 通过阿帕奇代理的也能获取到真实ip
* @param request
* @return
*/
public static String getRealIp(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
配置类:
package com.vrv.Govern.controller.Wx;
import com.github.wxpay.sdk.WXPayConfig;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
/**
* Created by 15117 on 2018/11/27.
*/
public class XCFWXPayConfig implements WXPayConfig {
private byte[] certData;
public XCFWXPayConfig(HttpServletRequest request) throws Exception {
//获取apiclient_cert.pem的路径
String savedDir = request.getSession().getServletContext().getRealPath("/");
String certPath = savedDir + "common/Wx/cert/apiclient_cert.pem";
File file = new File(certPath);
InputStream stream = new FileInputStream(file);
this.certData = new byte[(int) file.length()];
stream.read(this.certData);
stream.close();
}
@Override
public String getAppID() {
return "wx311357d055a3595wa";
}
@Override
public String getMchID() {
return "15352222781";
}
@Override
public String getKey() {
return "YzCkxvBtqdJbLxHM3333GxwoeGLUUcb";
}
@Override
public InputStream getCertStream() {
return new ByteArrayInputStream(this.certData);
}
@Override
public int getHttpConnectTimeoutMs() {
return 8000;
}
@Override
public int getHttpReadTimeoutMs() {
return 10000;
}
}
特别注意:
此文件下载地址:https://download.csdn.net/download/qq_41712834/11694154
绑定appid
按照申请的微信支付的数值填入
三:页面调用
页面访问:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>微信支付</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
<!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
<!--[if lt IE 9]>
<script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<h1>微信支付!!</h1>
<form role="form">
<div class="form-group">
<label for="price">支付金额</label>
<input type="text" class="form-control" value="0.01" readonly id="price" placeholder="">
</div>
<button type="button" onclick="sub()" class="btn btn-default">提交</button>
</form>
</div>
<script type="text/javascript" src="../common/js/jquery-3.3.1.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="../common/app/js/bootstrap.min.js"></script>
<script src="https://pv.sohu.com/cityjson?ie=utf-8"></script>
<script>
var ip = returnCitySN.cip;
function sub(){
$.ajax({
url:"../Home_WxPay/pay.active",
data:{'ip':ip},
type:'post',
dataType:'json',
success:function(r){
location.href=r.data;
}
});
}
</script>
</body>
</html>
使用时需要更换jquery 的路径
成功或失败调用的页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>支付成功</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<!-- HTML5 shim 和 Respond.js 是为了让 IE8 支持 HTML5 元素和媒体查询(media queries)功能 -->
<!-- 警告:通过 file:// 协议(就是直接将 html 页面拖拽到浏览器中)访问页面时 Respond.js 不起作用 -->
<!--[if lt IE 9]>
<script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
<![endif]-->
</head>
<body>
<h1><span class="glyphicon glyphicon-ok"></span> 支付成功!</h1>
<script src="../common/app/js/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="../common/app/js/bootstrap.min.js"></script>
</body>
</html>
使用时需要更换jquery 的路径
四:测试
调用页面
ps:不清楚的可私聊哦,