1、引入依赖:(对于依赖冲突自行解决)

<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<!--<version>3.4.9.B</version>-->
<version>3.5.0</version>
<exclusions>
<exclusion>
<artifactId>httpclient</artifactId>
<groupId>org.apache.httpcomponents</groupId>
</exclusion>
<exclusion>
<artifactId>commons-lang3</artifactId>
<groupId>org.apache.commons</groupId>
</exclusion>
<exclusion>
<artifactId>commons-beanutils</artifactId>
<groupId>commons-beanutils</groupId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>

2、

package com.dhht.wechat.controller;

import com.dhht.wechat.VO.PayVO;
import com.dhht.wechat.service.PayService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; /*
* @Author: sh
* @Description: WxPayController
* @Date: 11:06 2019/7/17
*/ @RestController
@RequestMapping("wechat/")
public class WxPayController { @Resource
private PayService payService; /**
* 微信支付统一下单接口(H5)
* @param payVO
* @param request
* @return
*/
@PostMapping(value = "pay",produces = "application/json;charset=UTF-8")
public String unifiedOrder(@RequestBody PayVO payVO, HttpServletRequest request){
return payService.unifiedOrder(payVO,request);
} /**
* 微信支付接收通知接口(供微信服务调用)
* @param xmlData
* @return
*/
@PostMapping(value = "pay/notify",produces = "application/json;charset=UTF-8")
public synchronized String payNotify(@RequestBody String xmlData){ return payService.payNotifyCallBack(xmlData);
} /**
* 退款结果通知接口
* @param xmlData
* @return
*/
@PostMapping("/notify/refund")
public synchronized String parseRefundNotifyResult(@RequestBody String xmlData) {
return payService.parseRefundNotifyResult(xmlData);
} }
package com.dhht.wechat.service;

import com.alibaba.fastjson.JSON;
import com.dhht.wechat.VO.PayVO;
import com.dhht.wechat.service.impservice.OrderRefundResultImplService;
import com.dhht.wechat.service.impservice.SealOrderImplService;
import com.dhht.wechat.service.impservice.SealOrderSealImplService;
import com.dhht.wechat.util.ConstantUtil;
import com.dhht.wechat.util.DateUtil;
import com.dhht.wechat.wxpay.MyX509TrustManager;
import com.dhht.wechat.wxpay.PayRespCodeMsg;
import com.dhht.wechat.wxpay.PayResultVO;
import com.dhht.wechat.wxpay.WechatPayConfigBean;
import com.dhht.wechat.wxpay.config.WxPayProperties;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.service.WxPayService;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import javax.annotation.Resource;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.net.ConnectException;
import java.net.URL;
import java.security.MessageDigest;
import java.text.MessageFormat;
import java.util.*; /**
* WxPayService
*/
@Service
public class PayService { @Resource
private WechatPayConfigBean wechatPayConfigBean; @Resource
private WxPayProperties wxPayProperties;// 第三方 @Resource
private SealOrderImplService sealOrderImplService; @Resource
private WxPayService wxService;// 第三方sdk // @Resource
// private OrderPayResultImplService orderPayResultImplService; @Resource
private OrderRefundResultImplService orderRefundResultImplService; @Value("${spbill_create_ip}")
private String SPBILL_CREATE_IP; @Value("${appSecret}")
private String appSecret; @Resource
WeiXinService weiXinService; @Resource
SealOrderSealImplService sealOrderSealImplService; /**
* 微信支付统一下单接口(H5)
*
* @param payVO
* @param request
* @return
*/
public String unifiedOrder(PayVO payVO, HttpServletRequest request) {
try { String orderId = payVO.getOrderId();
String code = payVO.getCode();
if (StringUtils.isEmpty(orderId) || StringUtils.isEmpty(code)) {
PayResultVO payResultVO = new PayResultVO(-1, "NO", null);
return JSON.toJSONString(payResultVO);
} WxPayOrderQueryResult payOrderQueryResult = wechatOrderQuery(orderId);// wxService.queryOrder(null, orderId);// 查询订单状态
String payOrderQuery_return_code = payOrderQueryResult.getReturnCode();// SUCCESS/FAIL
if (ConstantUtil.PAY_RETURN_CODE_NO.equals(payOrderQuery_return_code)) {// 通信失败:FAIL
PayResultVO queryPayResultVO = new PayResultVO(-1, payOrderQueryResult.getReturnMsg(), null);
return JSON.toJSONString(queryPayResultVO);// 订单查询接口通信失败,直接返回
} // 订单查询通信成功:SUCCESS // 若业务成功 /**
* trade_state状态如下:
* SUCCESS—支付成功
* REFUND—转入退款
* NOTPAY—未支付
* CLOSED—已关闭
* REVOKED—已撤销(刷卡支付)
* USERPAYING--用户支付中
* PAYERROR--支付失败(其他原因,如银行返回失败)商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付
*/
String trade_state = payOrderQueryResult.getTradeState();
if (!ConstantUtil.PAY_TRADE_STATE_NOTPAY.equals(trade_state) && null != trade_state) {// 非未支付状态下(可以为null-代表还未生成订单,故需过滤掉)
PayResultVO tradePayResultVO = new PayResultVO(-1, ConstantUtil.PAY_STATUS_MAP.get(trade_state), null);
return JSON.toJSONString(tradePayResultVO);
}
// 以下转入订单未支付处理或还没有生成订单(trade_state==null)的处理逻辑 //String openUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+wxPayProperties.getAppId()+"&secret="+appSecret+"&code="+code+"&grant_type=authorization_code";
String openId = weiXinService.getOpenId(code);//SendMsgUtil.httpRequest(openUrl,"GET","{}").getString("openid");// 获取openid
// 更新订单openId--2019-09-17
Map<String, Object> paMap = new HashMap<>();
paMap.put("orderId", orderId);
paMap.put("userOpenId", openId);
sealOrderImplService.updateOrderInfo(paMap);
// 获取本系统印章订单信息
Map<String, Object> orderDetails = sealOrderImplService.getOrderMapById(orderId);
String SUB_MCH_ID = (String) orderDetails.get("SUB_MCH_ID");// 营业网点扩展信息表中的子商户号-20190910
if (StringUtils.isEmpty(SUB_MCH_ID)) {// 若无配置子商户号退出
PayResultVO payResultVO = new PayResultVO(-1, "NO-SUB_MCH_ID", null);
return JSON.toJSONString(payResultVO);
}
String siteName = (String) orderDetails.get("siteName");// 营业网点名称(刻章店名称)
float orderPrice = ((BigDecimal) orderDetails.get("ORDER_AMOUNT")).floatValue();// 订单总金额
String bodyName = siteName + "-" + ConstantUtil.ADVANCE_PAY_GOODS_NAME;// 商品名称严格按照规范-公众号支付-例如(商家名称-销售商品类目)
// 设置统一下单请求参数
// 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置)
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
orderRequest.setAppid(wxPayProperties.getAppId());// 服务商appid
orderRequest.setMchId(wxPayProperties.getMchId());// 商户号
orderRequest.setSubMchId(SUB_MCH_ID);// 子商户号
String nonceStr = DateUtil.get32UUIDMilli();
orderRequest.setNonceStr(nonceStr);// 随机串,32位以内!
orderRequest.setSignType(wxPayProperties.getSignType());// 签名类型
orderRequest.setBody(bodyName);
orderRequest.setOutTradeNo(orderId);
orderRequest.setTotalFee(BaseWxPayRequest.yuanToFen(orderPrice + ""/*order.getTotalFee()*/));//元转成分
orderRequest.setSpbillCreateIp(SPBILL_CREATE_IP);// 终端IP
orderRequest.setNotifyUrl(wxPayProperties.getNotifyUrl());// 支付结果异步回调地址
orderRequest.setTradeType(wxPayProperties.getTradeType());// 交易类型
orderRequest.setOpenid(openId);// 设置openid
WxPayMpOrderResult wxPayUnifiedOrderResult = wxService.createOrder(orderRequest);// 统一下单接口调用结果 String appId = wxPayUnifiedOrderResult.getAppId();
String timeStamp = create_timestamp();
String package_ = wxPayUnifiedOrderResult.getPackageValue();// ConstantUtil.PACKAGE_SUFFIX + wxPayUnifiedOrderResult.getPackageValue();
String paySign = wxPayUnifiedOrderResult.getPaySign();
Map<String, Object> resultMapData = new HashMap<>();
resultMapData.put("appId", appId);
resultMapData.put("timeStamp", timeStamp);
resultMapData.put("package", package_);
resultMapData.put("paySign", paySign);
resultMapData.put("nonceStr", wxPayUnifiedOrderResult.getNonceStr());
resultMapData.put("signType", wxPayProperties.getSignType());
PayResultVO paySucessResultVO = new PayResultVO(0, "OK", resultMapData);
return JSON.toJSONString(paySucessResultVO);
} catch (Exception e) {
Map map = new HashMap();
map.put("data", e.getMessage());
PayResultVO payResultVO = new PayResultVO(-1, "NO", map);
return JSON.toJSONString(payResultVO);
}
} /**
* 支付回调
*
* @param xmlData
* @return
*/
public synchronized String payNotifyCallBack(String xmlData) {
try { WxPayOrderNotifyResult wxPayOrderNotifyResult = wxService.parseOrderNotifyResult(xmlData);// 解析xml字符串
String return_code = wxPayOrderNotifyResult.getReturnCode();// SUCCESS/FAIL if (ConstantUtil.PAY_RETURN_CODE_NO.equals(return_code)) {// 支付通信失败
return WxPayNotifyResponse.fail("FAIL");
}
// 以下通信成功操作
String out_trade_no = wxPayOrderNotifyResult.getOutTradeNo();// 商户系统内部订单号(即本系统印章订单号)
// 内部订单支付情况
Map<String, Object> orderDetails = sealOrderImplService.getOrderMapById(out_trade_no);
if (null != orderDetails) {
String paySta = (Integer) orderDetails.get("PAY_STATUS") + "";
if ((ConstantUtil.ORDER_PAYSTATUS_1_ + "").equals(paySta)) {// 已支付直接返回
return WxPayNotifyResponse.success("OK");
}
} if (ConstantUtil.PAY_RETURN_CODE_OK.equals(return_code)) {// 支付接口通信成功
String result_code = wxPayOrderNotifyResult.getResultCode();// SUCCESS/FAIL 是否真实支付成功 if (ConstantUtil.PAY_RETURN_CODE_OK.equals(result_code)) {// 支付成功
// 检查本库是否已经插入支付成功记录
// orderPayResultImplService.deleteByOrderId(out_trade_no);
//orderPayResultImplService.add(wxPayOrderNotifyResult);
//orderPayResultImplService.insertSelective(wxPayOrderNotifyResult);
sealOrderImplService.updateOrderPaySta(out_trade_no, ConstantUtil.ORDER_PAYSTATUS_1_);// 更新支付状态
// 推送微信内容-2019-09-18
sealOrderSealImplService.sendWXMsgToSite(out_trade_no); }
if (ConstantUtil.PAY_RETURN_CODE_NO.equals(result_code)) {// 支付失败
closePayOrder(out_trade_no);// 支付失败的话,需要关闭订单,才能重新支付
sealOrderImplService.upOrderRelation(out_trade_no);// 更新该订单的id,主要用于重新支付
sealOrderImplService.updateOrderPaySta(out_trade_no, ConstantUtil.ORDER_PAYSTATUS_2_);// 更新支付状态
}
return WxPayNotifyResponse.success("OK");
} else {// 支付结果通信失败
return WxPayNotifyResponse.fail("FAIL");
} } catch (Exception e) {
return WxPayNotifyResponse.fail("FAIL");
}
} /**
* 查询订单状态
*
* @param orderId
* @return
*/
public WxPayOrderQueryResult wechatOrderQuery(String orderId) {
try {
if (StringUtils.isEmpty(orderId)) {
return null;
}
Map<String, Object> orderDetails = sealOrderImplService.getOrderMapById(orderId);// 获取本系统订单的相关信息
String SUB_MCH_ID = (String) orderDetails.get("SUB_MCH_ID");// 营业网点扩展信息表中的子商户号-20190910
WxPayOrderQueryRequest wxPayOrderQueryRequest = new WxPayOrderQueryRequest();
wxPayOrderQueryRequest.setAppid(wxPayProperties.getAppId());
wxPayOrderQueryRequest.setMchId(wxPayProperties.getMchId());
wxPayOrderQueryRequest.setSubMchId(SUB_MCH_ID);// 子商户好最终通过orderId从本系统获取
wxPayOrderQueryRequest.setOutTradeNo(orderId);// 微信内部订单号与本系统订单号二选一
wxPayOrderQueryRequest.setNonceStr(DateUtil.get32UUIDMilli());
wxPayOrderQueryRequest.setSignType(wxPayProperties.getSignType());
WxPayOrderQueryResult wxPayOrderQueryResult = wxService.queryOrder(wxPayOrderQueryRequest);
return wxPayOrderQueryResult;
} catch (Exception e) {
WxPayOrderQueryResult wxPayOrderQueryResult = new WxPayOrderQueryResult();
wxPayOrderQueryResult.setReturnCode(ConstantUtil.PAY_RETURN_CODE_OK);
wxPayOrderQueryResult.setResultCode(ConstantUtil.PAY_RETURN_CODE_OK);
wxPayOrderQueryResult.setTradeState(null);
return wxPayOrderQueryResult;
}
} /**
* 关闭订单(关闭订单之后,重新提交支付需要更新订单号!)
*
* @param orderId
* @return
*/
public WxPayOrderCloseResult closePayOrder(String orderId) {
if (StringUtils.isEmpty(orderId)) {
return null;
}
try {
Map<String, Object> orderDetails = sealOrderImplService.getOrderMapById(orderId);// 获取本系统订单的相关信息
String SUB_MCH_ID = (String) orderDetails.get("SUB_MCH_ID");// 营业网点扩展信息表中的子商户号-20190910
WxPayOrderCloseRequest wxPayOrderCloseRequest = new WxPayOrderCloseRequest();
wxPayOrderCloseRequest.setAppid(wxPayProperties.getAppId());
wxPayOrderCloseRequest.setMchId(wxPayProperties.getMchId());
wxPayOrderCloseRequest.setSubMchId(SUB_MCH_ID);// 从本系统获取通过orderDetails
wxPayOrderCloseRequest.setOutTradeNo(orderId);
wxPayOrderCloseRequest.setNonceStr(DateUtil.get32UUIDMilli());
wxPayOrderCloseRequest.setSignType(wxPayProperties.getSignType());
WxPayOrderCloseResult wxPayOrderCloseResult = wxService.closeOrder(wxPayOrderCloseRequest);
return wxPayOrderCloseResult;
} catch (Exception e) {
return null;
}
} /**
* 订单退款(接口请求并非退款结果)
*
* @param orderId
* @return
*/
public PayResultVO refundPayOrder(String orderId) {
try {
if (StringUtils.isEmpty(orderId)) {
return null;
}
Map<String, Object> orderDetails = sealOrderImplService.getOrderMapById(orderId);// 获取本系统订单的相关信息 // 查询微信支付订单信息
WxPayOrderQueryResult wxPayOrderQueryResult = wechatOrderQuery(orderId);
String order_return_code = wxPayOrderQueryResult.getReturnCode();// 订单查询网络状态
if (ConstantUtil.PREPAYID_RETURN_CODE_NO.equals(order_return_code)) {
PayResultVO returnPayResultVO = new PayResultVO(-1, ConstantUtil.PAY_NETWORK_EXCEP, null);
return returnPayResultVO;
}
String order_result_code = wxPayOrderQueryResult.getResultCode();// 订单查询业务状态
if (ConstantUtil.PREPAYID_RETURN_CODE_NO.equals(order_result_code)) {
PayResultVO resultPayResultVO = new PayResultVO(-1, ConstantUtil.REFUND_FAIL_MSG, null);
return resultPayResultVO;
}
String order_trade_state = wxPayOrderQueryResult.getTradeState();// 订单状态(已支付、未支付等等)
if (!ConstantUtil.PAY_TRADE_STATE_SUCCESS.equals(order_trade_state)) {// 未支付成功,直接返回
PayResultVO tradePayResultVO = new PayResultVO(-1, ConstantUtil.REFUND_FAIL_MSG, null);
}
// 以下为订单已支付后续操作(只有order_trade_state为SUCCESS可获取如下参数)
String transaction_id = wxPayOrderQueryResult.getTransactionId();// 微信内部支付订单号
int total_fee = wxPayOrderQueryResult.getTotalFee();// 订单总金额
String sub_mch_id = wxPayOrderQueryResult.getSubMchId();// 订单子商户号
String out_trade_no = wxPayOrderQueryResult.getOutTradeNo(); WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
wxPayRefundRequest.setAppid(wxPayProperties.getAppId());
wxPayRefundRequest.setMchId(wxPayProperties.getMchId());
wxPayRefundRequest.setSubMchId(sub_mch_id);// 从本系统通过orderId获取
wxPayRefundRequest.setNonceStr(DateUtil.get32UUIDMilli());
wxPayRefundRequest.setSignType(wxPayProperties.getSignType());
wxPayRefundRequest.setTransactionId(transaction_id);
wxPayRefundRequest.setOutTradeNo(out_trade_no);// 商户内部订单号
String refundNo = DateUtil.get32UUIDMilli();// 生成商户内部退款单号
wxPayRefundRequest.setOutRefundNo(refundNo);// 商户内部退款单号!!!
wxPayRefundRequest.setTotalFee(total_fee);
wxPayRefundRequest.setRefundFee(total_fee);// !!!申请退款金额????
wxPayRefundRequest.setNotifyUrl(wxPayProperties.getRefundNotifyUrl());// 退款结果通知url
WxPayRefundResult wxPayRefundResult = wxService.refund(wxPayRefundRequest);// 订单退款接口
String refund_return_code = wxPayRefundResult.getReturnCode();// 退款接口网络状态
if (ConstantUtil.PREPAYID_RETURN_CODE_NO.equals(refund_return_code)) {
PayResultVO refundExPayVO = new PayResultVO(-1, ConstantUtil.REFUND_FAIL_MSG, null);
return refundExPayVO;
}
String refund_result_code = wxPayRefundResult.getResultCode();// 退款接口结果状态
if (ConstantUtil.PREPAYID_RETURN_CODE_NO.equals(refund_result_code)) {
PayResultVO refundFailPayVO = new PayResultVO(-1, ConstantUtil.REFUND_FAIL_MSG, null);
return refundFailPayVO;
} // 以下为退款成功操作
PayResultVO refundSuceesResultVO = new PayResultVO(0, "OK", wxPayRefundResult);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("refundNo", refundNo);// 内部退款单号
sealOrderImplService.updateOrderInfo(paramMap);
return refundSuceesResultVO;
} catch (Exception e) {
return null;
}
} /**
* 退款回调通知地址
*
* @param xmlData
* @return
*/
public synchronized String parseRefundNotifyResult(String xmlData) {
try {
WxPayRefundNotifyResult result = wxService.parseRefundNotifyResult(xmlData);
String return_code = result.getReturnCode();
if (ConstantUtil.PREPAYID_RETURN_CODE_NO.equals(return_code)) {// 通信失败
return WxPayNotifyResponse.fail("FAIL");
}
// 以下为通信成功返回的字段信息
WxPayRefundNotifyResult.ReqInfo reqInfo = result.getReqInfo();// 获取结果中的加密信息 /**
* SUCCESS-退款成功
* CHANGE-退款异常
* REFUNDCLOSE—退款关闭
*/
String refund_status = reqInfo.getRefundStatus();// 退款状态 if (ConstantUtil.REFUND_STATUS_0.equals(refund_status)) {// 成功
refund_status = ConstantUtil.ORDER_PAYSTATUS_3_ + "";
}
if (ConstantUtil.REFUND_STATUS_1.equals(refund_status)) {// 异常
refund_status = ConstantUtil.ORDER_PAYSTATUS_4_ + "";
}
if (ConstantUtil.REFUND_STATUS_2.equals(refund_status)) {// 关闭
refund_status = ConstantUtil.ORDER_PAYSTATUS_4_ + "";
}
String out_trade_no = reqInfo.getOutTradeNo();// 内部订单号
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("refundNo", out_trade_no);// 内部退款单号
paramMap.put("payStatus", refund_status);// 更新支付状态
sealOrderImplService.updateOrderInfo(paramMap);
orderRefundResultImplService.deleteByOrderdId(out_trade_no);// 删除订单
orderRefundResultImplService.addRefundInfo(result);// 添加退款 记录
return WxPayNotifyResponse.success("OK");
} catch (Exception e) {
return WxPayNotifyResponse.fail("FAIL");
}
} //****************************************************************************************************************** /**
* 获取微信签名信息(预支付订单信息)
*
* @param payVO
* @param request
* @return
*/
public synchronized String getWxPaySign(PayVO payVO, HttpServletRequest request) {
try {
if (null == payVO) {
return null;
}
String orderId = payVO.getOrderId();
String wxCode = payVO.getCode();
if (StringUtils.isEmpty(orderId) || StringUtils.isEmpty(wxCode)) {
return null;
}
// 获取openId
JSONObject openIdJson = getAccess_tokenByCode(wxCode);
int errcode_openId = openIdJson.getInt("errcode");
if (errcode_openId != 0) {// 调用获取openId接口不成功
PayRespCodeMsg payRespCodeMsg = new PayRespCodeMsg(errcode_openId, openIdJson.getString("errmsg"));
PayResultVO payResultVO = new PayResultVO(payRespCodeMsg, null);
return JSON.toJSONString(payResultVO);
}
String openid = openIdJson.getString("openid");// 用户唯一标识
String session_key = openIdJson.getString("session_key");// 会话秘钥 // 获取本地订单相关信息
Map<String, Object> orderDetails = sealOrderImplService.getOrderMapById(orderId);
String siteName = (String) orderDetails.get("siteName");// 营业网点名称(刻章店名称)
int orderPrice = ((BigDecimal) orderDetails.get("ORDER_AMOUNT")).intValue() * 100;
String bodyName = siteName + "-" + ConstantUtil.ADVANCE_PAY_GOODS_NAME;// 商品名称严格按照规范-公众号支付-例如(商家名称-销售商品类目)
String orderno = orderId;// "1234567890";
Integer total_fee = orderPrice;// "8.88";// 订单总费用,不能有小数点,以分为单位
String nonce_str = create_nonce_str();
String timestamp = create_timestamp(); // 获取预支付订单prepayId
SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
String prepayIdResult = getPrepayId(request, bodyName, orderno, total_fee, openid);// 获取预支付订单id方法,返回的xml字符串结果
Map<String, String> prepayIdResultMap = doXMLParse(prepayIdResult);// xml字符串转map
String prepayId_return_code = prepayIdResultMap.get("return_code");// SUCCESS/FAIL,此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断
if (ConstantUtil.PREPAYID_RETURN_CODE_NO.equals(prepayId_return_code)) {// 获取prepayId接口通信异常
PayRespCodeMsg preRespCodeMsg = new PayRespCodeMsg(-1, ConstantUtil.WECHAT_INTERFACE_EX_MSG);//
PayResultVO preResultVO = new PayResultVO(preRespCodeMsg, null);
return JSON.toJSONString(preResultVO);
}
// 获取prepayId的接口调用通信成功后
String prepayId_result_code = prepayIdResultMap.get("result_code");// SUCCESS/FAIL,业务结果
if (ConstantUtil.PAY_RETURN_CODE_NO.equals(prepayId_result_code)) {// 获取prepayId失败
PayRespCodeMsg preNo = new PayRespCodeMsg(-1, "NO");
PayResultVO preNoVO = new PayResultVO(preNo, null);
return JSON.toJSONString(preNoVO);
} // 微信预支付接口通信成功且业务结果成功
// 重新生成签名
parameters.put("appId", wechatPayConfigBean.getAppId());
parameters.put("timeStamp", timestamp);
parameters.put("nonceStr", nonce_str);
parameters.put("package", "prepay_id=" + prepayIdResultMap.get("prepay_id"));
parameters.put("signType", "MD5");
String sign = createSign("UTF-8", parameters);
parameters.put("prepay_id", "prepay_id=" + prepayIdResultMap.get("prepay_id"));
parameters.put("paySign", sign); PayResultVO okResult = new PayResultVO(0, "OK", parameters);
return JSON.toJSONString(okResult); } catch (Exception e) {
PayResultVO resultVO = new PayResultVO(-1, "FALSE", null);
return JSON.toJSONString(resultVO);
}
} public SortedMap<Object, Object> WapSignSignatureAction (HttpServletRequest request)throws Exception {
SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
String code = request.getParameter("code");
System.out.println("code-------------" + code);
// code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
// 通过code换取网页授权access_token
Map<String, String> data = getAccess_tokenByCode(code);
String openid = data.get("openid");
String tName = "名称";
String orderno = "1234567890";
String total_fee = "8.88";
String nonce_str = create_nonce_str();
String timestamp = create_timestamp();
// 获取prepayId
try {
String result = getPrepayId(request, tName, orderno, Integer.parseInt(total_fee), openid);
Map<String, String> map = doXMLParse(result);
// 重新生成签名
parameters.put("appId", wechatPayConfigBean.getAppId()
);
parameters.put("timeStamp", timestamp);
parameters.put("nonceStr", nonce_str);
parameters.put("package", "prepay_id=" + map.get("prepay_id"));
parameters.put("signType", "MD5");
String sign = createSign("UTF-8", parameters);
parameters.put("prepay_id", "prepay_id=" + map.get("prepay_id"));
parameters.put("paySign", sign);
} catch (Exception e) {
e.printStackTrace();
}
return parameters;
} /**
* 根据用户授权code获取access_token
*/
private JSONObject getAccess_tokenByCode(String code) {
Map<String, String> data = new HashMap<String, String>();
//String requestUrlMessageFormat = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code";
String requestUrlMessageFormat = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code";
String requestUrl = MessageFormat.format(requestUrlMessageFormat, wxPayProperties.getAppId() , appSecret , code);
String requestMethod = "GET";
String outputStr = "";
JSONObject json = httpRequest(requestUrl, requestMethod, outputStr);
//String access_token = (String) json.get("access_token");// 此参数最新接口文档没发现的
String openid = (String) json.get("openid");// 用户唯一标识
String session_key = json.getString("session_key");// 会话秘钥
String unionid = json.getString("unionid");// 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回
int errcode = json.getInt("errcode");// 错误码
String errmsg = json.getString("errmsg");// 错误信息
//data.put("access_token", access_token);
data.put("openid", openid);
data.put("session_key", session_key);
data.put("unionid", unionid);
data.put("errcode", errcode + "");
data.put("errmsg", errmsg);
return json;
} /**
* 发起https请求并获取结果
*
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return JSONObject(通过JSONObject.get ( key)的方式获取json对象的属性值)
*/
public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = {new MyX509TrustManager()};
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory(); URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf); httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod); if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect(); // 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
} // 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
System.err.println("Weixin server connection timed out.");
} catch (Exception e) {
System.err.println("https request error");
}
return jsonObject;
} /**
* 获取预支付订单id
*
* @param request
* @param name
* @param orderno
* @param total_fee
* @param openid
* @return
* @throws Exception
*/
public String getPrepayId(HttpServletRequest request, String name, String orderno, Integer total_fee,
String openid) throws Exception {
SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
parameters.put("appid", wechatPayConfigBean.getAppId() );// 服务商id
parameters.put("mch_id", wechatPayConfigBean.getMchId() );// 商户号
parameters.put("nonce_str", CreateNoncestr());// 随机字符串
parameters.put("body", name);// 商品描述
parameters.put("out_trade_no", orderno);// 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*且在同一个商户号下唯一
parameters.put("total_fee", total_fee);// 支付金额单位:分
parameters.put("spbill_create_ip", getIp2(request));// 支持IPV4和IPV6两种格式的IP地址。调用微信支付API的机器IP
parameters.put("notify_url", wechatPayConfigBean.getPayResultNotifyUrl());// 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数
parameters.put("trade_type", "JSAPI");// 交易类型,小程序取值如下:JSAPI,详细说明见
parameters.put("openid", openid);// 商户标识
parameters.put("time_expire", DateUtil.getTimeStamp());// (非必填)交易结束时间,需要动态传入,格式为yyyyMMddHHmmss-20190719114936
String sign = createSign("UTF-8", parameters);
parameters.put("sign", sign);
String requestXML = getRequestXml(parameters);
// 调用统一下单接口
String result = httpsRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST", requestXML);
System.out.println(result);
return result;
} public static String CreateNoncestr() {
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String res = "";
for (int i = 0; i < 16; i++) {
Random rd = new Random();
res += chars.charAt(rd.nextInt(chars.length() - 1));
}
return res;
} public static String getIp2(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (!org.apache.commons.lang3.StringUtils.isEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
// 多次反向代理后会有多个ip值,第一个ip才是真实ip
int index = ip.indexOf(",");
if (index != -1) {
return ip.substring(0, index);
} else {
return ip;
}
}
ip = request.getHeader("X-Real-IP");
if (!org.apache.commons.lang3.StringUtils.isEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
return ip;
}
return request.getRemoteAddr();
} @SuppressWarnings("rawtypes")
public String createSign(String characterEncoding, SortedMap<Object, Object> parameters) {
StringBuffer sb = new StringBuffer();
Set es = parameters.entrySet();
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=" + wechatPayConfigBean.getApiKey()
);
String sign = MD5Encode(sb.toString(), characterEncoding).toUpperCase();
return sign;
} 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 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];
} private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
"e", "f"}; @SuppressWarnings("rawtypes")
public static String getRequestXml(SortedMap<Object, Object> parameters) {
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
Set es = 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();
} /**
* * 发送https请求
*
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return 返回微信服务器响应的信息
*/
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = {new MyX509TrustManager()};
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod);
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 当outputStr不为null时向输出流写数据
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
return buffer.toString();
} catch (ConnectException ce) {
System.out.println("连接超时");
} catch (Exception e) {
System.out.println("请求异常");
}
return null;
} public static String create_nonce_str() {
return UUID.randomUUID().toString().replace("-", "");
} public static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
} /**
* 解析xml
*
* @param strxml
* @return
* @throws Exception
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static Map doXMLParse(String strxml) throws Exception {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\""); if (null == strxml || "".equals(strxml)) {
return null;
} Map m = new HashMap(); InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while (it.hasNext()) {
Element e = (Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if (children.isEmpty()) {
v = e.getTextNormalize();
} else {
v = getChildrenText(children);
} m.put(k, v);
}
// 关闭流
in.close();
return m;
} /**
* 获取子结点的xml
*
* @param children
* @return
*/
@SuppressWarnings("rawtypes")
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if (!children.isEmpty()) {
Iterator it = children.iterator();
while (it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if (!list.isEmpty()) {
sb.append(getChildrenText(list));
}
sb.append(value);
sb.append("</" + name + ">");
}
}
return sb.toString();
} }

微信支付第三方sdk使用的更多相关文章

  1. 微信支付的SDK曝出重大漏洞(XXE漏洞)

    一.背景 昨天(2018-07-04)微信支付的SDK曝出重大漏洞(XXE漏洞),通过该漏洞,攻击者可以获取服务器中目录结构.文件内容,如代码.各种私钥等.获取这些信息以后,攻击者便可以为所欲为,其中 ...

  2. 微信支付V3 SDK Payment Spring Boot 1.0.6 发布,实现留守红包,助力抗疫

    春节将至,为防控疫情,多地政府提倡员工.外来务工者留守本地过年,并鼓励企业向员工发放"留守红包".为此,微信支付推出"春节留守红包"能力,希望可以协助有发放需求 ...

  3. 微信支付PHP SDK —— 公众号支付代码详解

    在微信支付 开发者文档页面 下载最新的 php SDK http://mch.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1 这里假设你已经申请完微 ...

  4. 微信支付官方SDK V3 .NET版的坑

    但是支付成功后却不能正确的执行支付结果js回调函数.看看其页面的点击事件是放在asp:Button上面的.我们知道在asp.net webform中,按钮的点击是有页面回调后台的.也就是其实点击了之后 ...

  5. Unity接入微信登录 微信分享 微信支付 支付宝SDK

    你将会学到的unity集成SDK游戏中接入微信支付与支付宝支付游戏中接入微信登录与微信分享 目录 mp4格式,大小2.2GB 扫码时备注或说明中留下邮箱 付款后如未回复请至https://shop13 ...

  6. Android应用之——微信微博第三方sdk登录分享使用过程中的一些常见问题

    前言 近期在使用第三方登录和分享的过程中遇到了非常多问题,一方面能够归结为自己经验的不足,还有一方面事实上也说明了官方文档的含糊不清.这篇博文不会写关于怎样使用第三方登录分享,由于官方文档已经写明了步 ...

  7. 微信支付.NET SDK 中的BUG(存疑)

    BUG出现在类文件WxPayData.cs中的FromXml(string xml)方法 /** * @将xml转为WxPayData对象并返回对象内部的数据 * @param string 待转换的 ...

  8. Android微信支付SDK

    App对接微信调起微信支付需要在微信平台注册,鉴别的标识就是App的包名,所以将申请的包名单独打包成一个Apk文件,则在其他的App调起此Apk的时候同样可以起到调用微信支付的功能.这样就实现了调起微 ...

  9. iOS-关于微信支付

    突然发现的一篇文章,这位博主介绍的还是挺详细的,给大家分享一下 不懂的也可以咨询我qq:564702640 1.申请接入 详见 微信支付申请接入 . 创建应用+审核通过,你将得到:APP_ID.APP ...

随机推荐

  1. @echo off命令

    在C盘下新建一个文本文档,将名字改为1.bat.  打开/编辑,输入call cmd.cmd是命令提示符.运行该文件,出现命令提示符窗口,在该窗口下可以运行各种命令.由图1.1可见,在第一行显示C:\ ...

  2. 自己安装windows版本的Flink

    参照 https://blog.csdn.net/clj198606061111/article/details/99694033 我自己做一遍 找到对应的网址 https://flink.apach ...

  3. 摩尔纹滤镜moir

    function moir(imgData) { var width = imgData.width, height = imgData.height, pixelData = imgData.dat ...

  4. 【LeetCode】160. 相交链表

    题目 输入两个链表,找出它们的第一个公共节点. 如下面的两个链表: 在节点 c1 开始相交. 示例 1: 输入:intersectVal = 8, listA = [4,1,8,4,5], listB ...

  5. python--txt文件处理

    1.打开文件的模式主要有,r.w.a.r+.w+.a+ file = open('test.txt',mode='w',encoding='utf-8') file.write('hello,worl ...

  6. Fragment 知识巩固

    重新学习 Fragment 1.Fragment 的生命周期 想要熟练使用 Fragment,那么必须要弄懂它的生命周期. 我们可以先看一下 Fragment 生命周期和 Activity 生命周期的 ...

  7. GPRS模块

    一.参考网址 1.AT指令(中文详解版)(二)

  8. SQL笔记整理

  9. GTK入门

    环境准备 官网下载 GTK 源码包,因为本机 GLib 版本不够,下载一个非最新版的 GTK3.8.0 先学习用 直接阅读 "/gtk+-3.8.0/docs/reference/gtk/h ...

  10. BIOS与UEFI

    BIOS BIOS是英文"Basic Input Output System"的缩略词,直译过来后中文名称就是"基本输入输出系统".在IBM PC兼容系统上,是 ...