JAVA實現微信支付
阿新 • • 發佈:2019-01-31
1.微信支付官方文件微信官網連結
2.可以看到這些支付方式。
3.在此介紹公眾號支付和app支付。後面的開發基本看下文件就沒什麼問題了。
4.開發之前需要準備前期公眾。
5.首先需要申請公眾號並且開通支付等設定一些配置東西,這裡就不廢話了。
6.程式碼如下:
一、公眾號網頁支付(H5調起支付)
package com.common.action;
import java.io.BufferedOutputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext ;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import com.common.util.PoUtil;
import com.common.util .RequestUtil;
import com.common.util.ResponseResultUtil;
import com.common.util.ResultBeanUtil;
import com.common.util.TokenUtil;
import com.common.util.wx.WeixinPayUtil;
import com.common.util.wx.XMLUtil;
import com.frame.base.dto.Query;
import com.frame.enums.DeletedStatus;
import com.frame.enums.PlatformType;
import com.opensymphony.xwork2.ActionSupport;
import com.sfc.service.interfaces.ISfcFormOrderServiceCustom;
@ParentPackage("struts-framework")
@Namespace("/wxPayTools")
@SuppressWarnings("all")
public class WxPayToolsAction extends ActionSupport{
private static final long serialVersionUID = 4809391090975348475L;
private static final Log logger = LogFactory.getLog(WxPayToolsAction.class);
protected HttpServletRequest request = ServletActionContext.getRequest();
protected HttpServletResponse response = ServletActionContext.getResponse();
@Autowired
@Qualifier("tSysWxPayConfigCustomService")
private ITSysWxPayConfigServiceCustom tSysWxPayConfigCustomService;
@Autowired
@Qualifier("terminalUserService")
private ITerminalUserService terminalUserService;
/**
* 獲取action類名
* @return
*/
private String getActionName(){
return this.getClass().getSimpleName();
}
/**
* 微信公眾號支付
*/
public void wxPay(){
String methodName = "wxPay";
String message = "";
try{
String ecid = RequestUtil.getParameter(request, "ecid");
String orderNum = RequestUtil.getParameter(request, "orderNum");
String orderMoney = RequestUtil.getParameter(request, "orderMoney");
String userId = RequestUtil.getParameter(request, "userId");
String notifyUrl = RequestUtil.getParameter(request, "notifyUrl");
String body = RequestUtil.getParameter(request, "body");
String detail = RequestUtil.getParameter(request, "detail");
TSysWxPayConfigCustom wxPayConfigCustom = tSysWxPayConfigCustomService.getTSysWxPayConfigCustom(ecid);
if(wxPayConfigCustom == null){
ResponseUtils.renderJsonObject(response, ResponseResultUtil.returnFailResult(ResultBeanUtil.MSG_FAIL, "查詢配置資訊為空");
return;
}
// 獲取 prepayId
String prepayId= "";
Map<String, Object> mrsInfo = new HashMap<String, Object>();
SortedMap<String, String> wxInfo = new TreeMap<>();
wxInfo.put("orderNum",orderNum);
wxInfo.put("orderMoney",orderMoney);
wxInfo.put("body",body);
wxInfo.put("detail",detail);
Map<String, String> data = new HashMap<String,String>();
//微信公眾號手機網頁支付
TerminalUser terminalUser = terminalUserService.findObjById(userId);
if(terminalUser == null){
message = "查詢資料為空terminalUser="+terminalUser ;
ResponseUtils.renderJsonObject(response, ResponseResultUtil.returnFailResult(ResultBeanUtil.MSG_FAIL, message));
return;
}
String openId = terminalUser.getOpenId();
if(StringUtil.isEmptyOrNullStr(openId)){
ResponseUtils.renderJsonObject(response, ResponseResultUtil.returnFailResult(ResultBeanUtil.MSG_FAIL, "使用者openid為空openId="+openId));
return;
}
wxInfo.put("openId", openId);
// 根據prepayId簽名
prepayId = WeixinPayUtil.getWxJsPrepayId(request, response, wxInfo, wxPayConfigCustom,notifyUrl);
data = weixiPayUtil.createWxJsSignByPrepayId(request, response, prepayId, wxPayConfigCustom);
if (StringUtil.isEmptyOrNullStr(prepayId) || "-1".equals(prepayId)) {
message = methodName + " 方法 微信支付 ,微信公眾號手機網頁支付獲取預支付 prepayId " + prepayId + " 有誤!";
logger.error(message);
ResponseUtils.renderJsonObject(response,ResponseResultUtil.returnExceptionResult(ResultBeanUtil.MSG_EXCEPTION, message));
return;
}
mrsInfo.put("wxJsApi", data);
ResponseUtils.renderJsonObject(response, ResponseResultUtil.returnSuccResult(mrsInfo));
}catch(Exception e){
logger.error(getActionName() + "類的" + methodName + " 方法異常了exception=" + e.getMessage(), e);
e.printStackTrace();
ResponseUtils.renderJsonObject(response, ResponseResultUtil.returnExceptionResult(
ResultBeanUtil.MSG_EXCEPTION, getActionName() + "類的" + methodName + " 方法異常了!"));
}
}
}
package com.common.util.wx;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.xcx.util.Sign;
/**
* 微信支付工具類
* @ClassName: WeixiPayUtil
* @Description: 微信支付工具
* @author Administrator
* @date 2017年4月28日 下午12:02:12
*
*/
public class WeixinPayUtil {
private static Logger logger = LoggerFactory.getLogger(WeixinPayUtil.class);
public static final String RETURN_CODE_SUCC = "SUCCESS";
public static final String RETURN_CODE_FAIL = "FAIL";
public static final String JSAPI_PREPAY_ID = "jsapi_prepayId_";
public static final String APP_PREPAY_ID = "app_prepayId_";
protected static HttpServletRequest request = ServletActionContext.getRequest();
protected static HttpServletResponse response = ServletActionContext.getResponse();
public static SortedMap<String,String> getOrderInfoMap(Map<String, Object> mrsInfo, List<Map<String, Object>> productList){
SortedMap<String,String> orderInfo = new TreeMap<String, String>();
orderInfo.put("userId", mrsInfo.get("userId").toString());
orderInfo.put("orderNum", mrsInfo.get("orderNum").toString());
orderInfo.put("orderMoney", mrsInfo.get("allMoney").toString());
String subject = "",body="";
int bookCount = 0;
if(productList!=null && productList.size()>0){
for (Map<String, Object> shopOrderDetail : productList) {
subject = subject + shopOrderDetail.get("productName") + " , ";
bookCount = bookCount + StrUtil.getIntValue(shopOrderDetail.get("productCount").toString());
}
}
if(subject.contains(",")){
if(subject.length()>25){
subject = subject.substring(0,25)+"......";
}
subject = subject.substring(0,subject.length()-3);// 去掉最後一個,號或者最後一個.號
}
body = "訂單:"+mrsInfo.get("orderNum")+" 共包含"+bookCount+"件商品。";
orderInfo.put("body", body);
orderInfo.put("detail", subject);
return orderInfo;
}
/**
* 獲取JSAPI預支付ID
* @param request
* @param response
* @param orderInfo 包括欄位orderNum,orderMoney(單位:分),myNotifyUrl(自定義回撥地址時,可空),openId,detail(可空),body
* @param wxPayConfigCustom
* @param selfNotifyUrl 自定義通知連結
* @return
*/
public static String getWxJsPrepayId(HttpServletRequest request, HttpServletResponse response, Map<String,String> orderInfo, TSysWxPayConfigCustom wxPayConfigCustom, String selfNotifyUrl){
String methodName = "getWxJsPrepayId";
// 微信配置資訊
String wxappId = wxPayConfigCustom.getPublicAppId(); // 公眾號的唯一標識
String wxappSecret = wxPayConfigCustom.getPublicSecret(); // 微信公眾平臺應用APPSECRET
// 訂單資訊
String out_trade_no = orderInfo.get("orderNum");//訂單號
logger.info("out_trade_no="+out_trade_no);
String prepayId = getJsapiPrepayIdRedis(out_trade_no);
if(!StringUtil.isEmpty(prepayId)){
return prepayId;
}
String orderMoney = orderInfo.get("orderMoney");
logger.info("orderMoney="+orderMoney);
// 呼叫公共支付介面傳的自定義業務回撥通知地址
String myNotifyUrl = orderInfo.get("myNotifyUrl");
// 金額轉化為分為單位
float sessionmoney = Float.parseFloat(orderMoney);
String finalmoney = String.format("%.2f", sessionmoney);
String total_fee = Integer.parseInt(finalmoney.replace(".", "")) + "";
String detail = orderInfo.get("detail");
String openId = orderInfo.get("openId");
logger.info("openId="+openId);
// 商品描述
String body = orderInfo.get("body");
logger.info("body="+body);
if(StringUtil.isEmptyAnyOf(out_trade_no, orderMoney, body, openId)){
logger.info(getClassName()+"類 "+ methodName +"方法,orderNum,orderMoney,body,openId引數必須都不為空!");
return "-1";
}
// 商戶相關資料
String wxpartner = wxPayConfigCustom.getPublicMchId();
String wxpartnerkey = wxPayConfigCustom.getPublicKey();
// 商戶號
String mch_id = wxpartner;
// 隨機數
String nonce_str = Sha1Util.getNonceStr();
//附加資料
String attach = getAttachKey(out_trade_no, myNotifyUrl);
// 訂單生成的機器 IP
String spbill_create_ip = request.getRemoteAddr();
// 這裡notify_url是 支付完成後微信發給該連結資訊,可以判斷會員是否支付成功,改變訂單狀態等。
String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
String notify_url = url;
if (StringUtil.isEmpty(selfNotifyUrl)) {
notify_url += WeixinConfig.notify_url;//支付調起的連結/weiXinPay/wei_xin_pay!payNotify.action
} else {
notify_url += selfNotifyUrl;
}
String trade_type = WeixinConfig.trade_type_jsapi;//填寫JSAPI
SortedMap<String, String> packageParams = new TreeMap<String, String>();
packageParams.put("appid", wxappId);
packageParams.put("mch_id", mch_id);
packageParams.put("nonce_str", nonce_str);
packageParams.put("body", body);
if (StringUtil.isNotEmpty(detail)) {
packageParams.put("detail", detail);
}
packageParams.put("attach", attach);
packageParams.put("out_trade_no", out_trade_no);
packageParams.put("total_fee", total_fee);
packageParams.put("spbill_create_ip", spbill_create_ip);
packageParams.put("notify_url", notify_url);
packageParams.put("trade_type", trade_type);
packageParams.put("openid", openId);
RequestHandler reqHandler = new RequestHandler(request, response);
reqHandler.init(wxappId, wxappSecret, wxpartnerkey);
String sign = reqHandler.createSign(packageParams);
String xml="<xml>"+
"<appid>"+wxappId+"</appid>"+
"<mch_id>"+mch_id+"</mch_id>"+
"<nonce_str>"+nonce_str+"</nonce_str>"+
"<sign>"+sign+"</sign>"+
"<body><![CDATA["+body+"]]></body>";
if(StringUtil.isNotEmpty(detail)){
xml += "<detail><![CDATA["+detail+"]]></detail>";
}
xml += "<attach>"+attach+"</attach>"+
"<out_trade_no>"+out_trade_no+"</out_trade_no>"+
"<total_fee>"+total_fee+"</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>";
logger.info(getClassName()+"類 "+ methodName +"方法,xml="+ xml);
String createOrderURL = WeixinConfig.prepay_url;
try {
prepayId = GetWxOrderno.getPayNo(createOrderURL, xml);
setJsapiPrepayIdRedis(out_trade_no, prepayId);
logger.info(getClassName()+"類 "+ methodName +"方法,生成 prepayId="+prepayId+"||orderNum="+out_trade_no);
} catch (Exception e) {
logger.error(getClassName()+"類 "+ methodName +"方法,生成 prepayId 出錯了", e);
e.printStackTrace();
}
return prepayId;
}
package com.shopn.util;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.common.model.TSysWxPayConfigCustom;
import net.sf.json.JSONObject;
public class weixiPayUtil {
private static Logger logger = LoggerFactory.getLogger(weixiPayUtil.class);
//封裝H5請求的引數
public static Map<String,String> createWxJsSignByPrepayId(HttpServletRequest request, HttpServletResponse response, String prepayId,TSysWxPayConfigCustom wxPayConfigCustom){
String wxappid = WeixinpayConfig.wxappid;
String wxappsecret = WeixinpayConfig.wxappsecret;
String partnerkey = WeixinpayConfig.wxpartnerkey;
if(wxPayConfigCustom!=null){
if(!StringUtil.isEmptyOrNullStr(wxPayConfigCustom.getPublicAppId())){
wxappid = wxPayConfigCustom.getPublicAppId();
wxappsecret = wxPayConfigCustom.getPublicSecret();
partnerkey = wxPayConfigCustom.getPublicKey();
}
}
String noncestr = Sha1Util.getNonceStr();
String timeStamp = Sha1Util.getTimeStamp();
String signType = WeixinpayConfig.sign_type_md5;
String packageStr = "prepay_id="+prepayId;
SortedMap<String,String> params = new TreeMap<String,String>();
params.put("appId", wxappid);
params.put("timeStamp",timeStamp);
params.put("nonceStr", noncestr);
params.put("package", packageStr);
params.put("signType", signType);
//生成支付簽名,這個簽名 給 微信支付的呼叫使用
RequestHandler reqHandler = new RequestHandler(request, response);
reqHandler.init(wxappid, wxappsecret, partnerkey);
String paySign = reqHandler.createSign(params);
Map<String,String> map = new HashMap<String, String>();
map.put("appId", wxappid);
map.put("nonceStr", noncestr);
map.put("timeStamp", timeStamp);
map.put("signType", signType);
map.put("packageStr", packageStr);
map.put("paySign", paySign);
logger.info("createWxJsSignByPrepayId方法中生成 finalSign "+paySign);
return map;
}
}
}
生成微信公眾號H5發起的支付引數,然後通前端H5調起支付就可以了。H5發起支付微信公眾號連結