//核心代码
package com.mywxpay;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import com.comm.Utils;
import github.wxpay.sdk.WXPay;
import github.wxpay.sdk.WXPayConfig;
import github.wxpay.sdk.WXPayConstants;
import github.wxpay.sdk.WXPayUtil;
import github.wxpay.sdk.WXPayConstants.SignType;
public class MyWxPay {
//1 native 2 app
public static Map<String,Object> Order(HttpServletRequest request,int iTradeType,String body,String outTradeNo,BigDecimal totalAmount)
{
WXPayConfig config = null;
try {
config = new NativeConfig();
WXPay wxpay = new WXPay(config,SignType.MD5);
Map<String,String> data = new HashMap<String,String>();
data.put("body", body); //商品描述信息
data.put("out_trade_no",outTradeNo); //商户订单号 32个字符内,只能是数字、大小写字母
int totalFee = totalAmount.multiply(new BigDecimal(String.valueOf(100.00))).intValue();
data.put("total_fee",totalFee + "");//订单总金额,单位为分
String spbill_create_ip = Utils.getIpAddr(request);
data.put("spbill_create_ip", spbill_create_ip);//支持IPV4和IPV6两种格式的IP地址。调用微信支付API的机器IP
if(iTradeType == 1) //native
{
data.put("trade_type","NATIVE"); //交易类型 JSAPI--JSAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付,MWEB--H5支付
data.put("notify_url", WXPayConstants.NATIVE_NOTIFY_URL);
}else if(iTradeType == 2) //app
{
data.put("trade_type","APP"); //交易类型 JSAPI--JSAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付,MWEB--H5支付
data.put("notify_url", WXPayConstants.APP_NOTIFY_URL);
}
Map<String, String> resp = wxpay.unifiedOrder(data);//微信sdk集成方法, 统一下单接口unifiedOrder, 此处请求 MD5加密 加密方式
//通信结果
if("SUCCESS".equals(resp.get("return_code")))
{
//业务结果
if("SUCCESS".equals(resp.get("result_code")))
{
String prepayId = resp.get("prepay_id");
//System.out.println("prepayId = " + prepayId);
if (StringUtils.isNotEmpty(prepayId))
{
//System.out.println("enter" + " code url = " + resp.get("code_url"));
//微信订单创建成功,返回给前端调起微信支付的必要参数
Map<String,String> wxPayMap = new HashMap<>();
//native 扫码
if(iTradeType == 1)
{
wxPayMap.put("code_url", resp.get("code_url"));
//native只要返回二维码
Map<String,Object> mapNative = new HashMap();
mapNative.put("code_url",resp.get("code_url"));
return mapNative; //得到二维码立即返回
}else if(iTradeType == 2) //app 调起微信支付
{
//参与签名的字段名为appid,partnerid,prepayid,noncestr,timestamp,package。注意:package的值格式为Sign=WXPay
wxPayMap.put("appid", config.getAppID());
wxPayMap.put("timestamp", String.valueOf(WXPayUtil.getCurrentTimestamp()));
wxPayMap.put("noncestr", resp.get("nonce_str"));
wxPayMap.put("partnerid", config.getMchID());
wxPayMap.put("package", "Sign=WXPay");
wxPayMap.put("prepayid", prepayId);//微信生成的预支付会话标识
}
// 通过sdk WXPayUtil类加密, 注意, 此处使用 MD5加密 方式
String sign = WXPayUtil.generateSignature(wxPayMap, config.getKey());
Map<String, Object> result = new HashMap<>();
result.put("paySign", sign);
result.put("appId", config.getAppID());
result.put("timeStamp", String.valueOf(WXPayUtil.getCurrentTimestamp()));
result.put("nonceStr", resp.get("nonce_str"));
result.put("signType", "MD5");
//app 支付
if (iTradeType == 2) {
result.put("partnerid", config.getMchID());
result.put("prepayid", prepayId);
result.put("packageStr", "Sign=WXPay");
}
return result;
}
}else
{
System.out.println("业务失败 code= " + resp.get("err_code") + " " + resp.get("err_code_des"));
}
}else
{
System.out.println("通信失败:" + resp.get("return_msg"));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* 微信异步回调
*/
public synchronized static Map<String, String> CbNotify(HttpServletRequest request, HttpServletResponse response) {
try {
InputStream is = request.getInputStream();
//将InputStream转换成String
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
String notifyData = sb.toString(); // 支付结果通知的xml格式数据
WXPayConfig config = null;
//native 配置可不区分
config = new NativeConfig();
WXPay wxpay = new WXPay(config,SignType.MD5);
Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData); // 转换成map
if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
// 签名正确
String returnCode = notifyMap.get("return_code");//通信标识
if (StringUtils.isNotEmpty(returnCode) && "SUCCESS".equals(returnCode)) {// 通信成功
// 支付结果代码
String resultCode = notifyMap.get("result_code");//业务结果
if (StringUtils.isNotEmpty(resultCode) && "SUCCESS".equals(resultCode)) {// 结果处理成功
String tradeType = notifyMap.get("trade_type");
int iTradeType = 0;
if(tradeType.equals("NATIVE"))
{
iTradeType = 1;
}else if(tradeType.equals("APP"))
{
iTradeType = 2;
}
//商户订单号
String outTradeNo = notifyMap.get("out_trade_no");
//支付成功,设置订单状态为已完成支付
OrderManager orderManager = new OrderManager();
orderManager.FinishOrder(outTradeNo);
//自己的成功业务
System.out.println("支付成功!");
PrintWriter out = response.getWriter();
out.print("<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> </xml>");
out.flush();
out.close();
}else
{
System.out.println("支付结果:业务失败");
}
}else
{
//通信失败
System.out.println("支付结果:通信失败");
}
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
//调用代码
package com.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.Map;
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 com.comm.MD5;
import com.mywxpay.MyWxPay;
import com.mywxpay.OrderManager;
@WebServlet("/WxPayServlet")
public class WxPayServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public WxPayServlet() {
super();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
System.out.println("enter");
String strCheck = request.getParameter("check");
System.out.println("check = " + strCheck);
if(strCheck != null && strCheck.equals("qg123456"))
{
String strType = request.getParameter("type");
if(strType.equals("1"))
{
String goodsId = request.getParameter("goodsId");
String orderNo = System.currentTimeMillis() + goodsId;
String playerId = request.getParameter("playerId");
orderNo = MD5.MD5EncodeUtf8(orderNo);
System.out.println("no = " + orderNo);
String body = "全民来掼蛋";
String price = request.getParameter("price");
System.out.println("price = " + request.getParameter("price"));
Map<String,Object> result = MyWxPay.Order(request, Integer.parseInt(strType),body,orderNo,new BigDecimal(price));
if(result == null)
{
out.print("error");
System.out.println("支付申请异常");
}else
{
//申请支付成功,创建订单号
OrderManager orderManager = new OrderManager();
orderManager.CreateOrder(1, playerId, goodsId, new BigDecimal(price), orderNo,System.currentTimeMillis());
out.print(result.get("code_url"));
}
}
}
out.flush();
out.close();
}
}
//回调代码
package com.servlet;
import java.io.IOException;
import java.math.BigDecimal;
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 com.mywxpay.MyWxPay;
@WebServlet("/WxCbServlet")
public class WxCbServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public WxCbServlet() {
super();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
MyWxPay.CbNotify(request,response);
}
}
//配置代码
package com.mywxpay;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import github.wxpay.sdk.IWXPayDomain;
import github.wxpay.sdk.WXPayConfig;
import github.wxpay.sdk.WXPayConstants;
public class NativeConfig extends WXPayConfig{
private byte[] certData;
private String appId = "";
private String key= "";//商户自定义32位密钥
private String mchId = "";//商户号
public NativeConfig() throws Exception { // 构造方法读取证书, 通过getCertStream 可以使sdk获取到证书
/* String certPath = "/data/config/chidori/apiclient_cert.p12";
File file = new File(certPath);
InputStream certStream = new FileInputStream(file);
this.certData = new byte[(int) file.length()];
certStream.read(this.certData);
certStream.close();*/
}
@Override
public String getAppID() {
return appId;
}
@Override
public String getMchID() {
return mchId;
}
@Override
public String getKey() {
return key;
}
@Override
public InputStream getCertStream() {
return new ByteArrayInputStream(this.certData);
}
@Override
public IWXPayDomain getWXPayDomain() { // 这个方法需要这样实现, 否则无法正常初始化WXPay
IWXPayDomain iwxPayDomain = new IWXPayDomain() {
@Override
public void report(String domain, long elapsedTimeMillis, Exception ex) {
}
@Override
public IWXPayDomain.DomainInfo getDomain(WXPayConfig config) {
return new IWXPayDomain.DomainInfo(WXPayConstants.DOMAIN_API, true);
}
};
return iwxPayDomain;
}
}
//工具类 md5
package com.comm;
import java.security.MessageDigest;
public class MD5 {
public static String SALT = "23543dfggeelysdafaqj23ou89ZXcj@#$@#$#@KJdjklj;D../dSF.,";
// 这里主要是遍历8个byte,转化为16位进制的字符,即0-F
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];
}
/**
* 返回大写MD5
*
* @param origin
* @param charsetname
* @return
*/
private static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = 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.toUpperCase();
}
public static String MD5EncodeUtf8(String origin) {
origin = origin + SALT;
return MD5Encode(origin, "utf-8");
}
private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
"e", "f" };
}
//工具类
package com.comm;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import javax.servlet.http.HttpServletRequest;
public class Utils {
public static byte[] ToBytes(int n) {
byte[] b = new byte[4];
b[3] = (byte) (n & 0xff);
b[2] = (byte) (n >> 8 & 0xff);
b[1] = (byte) (n >> 16 & 0xff);
b[0] = (byte) (n >> 24 & 0xff);
return b;
}
public static int ToInt(byte[] bytes){
int a=(bytes[0] & 0xff) << 24;
int b = (bytes[1] & 0xff) << 16;
int c = (bytes[2] & 0xff) << 8;
int d = (bytes[3] & 0xff);
return a|b|c|d;
}
/**
* 获取登录用户的IP地址
*
* @param request
* @return
*/
public static String getIpAddr(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();
}
if (ip.equals("0:0:0:0:0:0:0:1")) {
ip = "127.0.0.1";//"本地";
}
if (ip.split(",").length > 1) {
ip = ip.split(",")[0];
}
return ip;
}
public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {
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=" + API_KEY);
String sign = MD5.MD5EncodeUtf8(sb.toString()).toUpperCase();
return sign;
}
}