<!-- 微信 -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.github.liyiorg</groupId>
<artifactId>weixin-popular</artifactId>
<version>2.8.14</version>
</dependency>
微信H5支付,参考了很多资料踩了不少坑,终于做出来了,做个记录
import java.util.UUID;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import weixin.popular.api.PayMchAPI;
import weixin.popular.bean.paymch.Refundquery;
import weixin.popular.bean.paymch.RefundqueryResult;
import weixin.popular.bean.paymch.SecapiPayRefund;
import weixin.popular.bean.paymch.SecapiPayRefundResult;
import weixin.popular.client.LocalHttpClient;
public class WeixinPayUtils {
/**
* 公众号AppId
*/
public static final String APP_ID = "你的公众号AppId";
/**
* 公众号AppSecret
*/
public static final String APP_SECRET = "你的公众号AppSecret";
/**
* 微信支付商户号
*/
public static final String MCH_ID = "你的商户号";
/**
* 微信支付API秘钥
*/
public static final String API_KEY = "你的支付API秘钥";
/**
* 回调域名
* 全域名比如 https://www.baidu.com
*/
public static final String REDIRECT_DOMAIN = "你的全域名";
// 商户支付证书路径
// 退款必备
private static final String API_CLIENT_CERT_PATH = "/opt/cert_wxh5pay/apiclient_cert.p12";
// 加载商户支付证书文件;
// 退款必备
static {
LocalHttpClient.initMchKeyStore(MCH_ID, API_CLIENT_CERT_PATH);
}
private static final WxMpService wxMpService = new WxMpServiceImpl();
private static final WxPayService wxPayService = new WxPayServiceImpl();
static {
WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();
config.setAppId(APP_ID);
config.setSecret(APP_SECRET);
wxMpService.setWxMpConfigStorage(config);
WxPayConfig payConfig = new WxPayConfig();
payConfig.setAppId(APP_ID);
payConfig.setMchId(MCH_ID);
payConfig.setMchKey(API_KEY);
payConfig.setSignType(WxPayConstants.SignType.MD5);
// h5公众号支付
payConfig.setTradeType("MWEB");
// 这里是调用支付接口之后 微信调用的回调路径
payConfig.setNotifyUrl(REDIRECT_DOMAIN + "/ymlwx");
wxPayService.setConfig(payConfig);
}
public static WxMpService wxMpService() {
return wxMpService;
}
public static WxPayService wxPayService() {
return wxPayService;
}
/**
* @description:微信退款业务封装(支付押金退还);
* @param PayLog
* order:支付订单信息 Double refundAmount:退款金额
* @return 微信退款接口返回数据 true 退款成功 false 退款失败
*/
public static boolean refundOrder(String orderId, Integer refundAmount) {
// 调用微信支付退款接口;
SecapiPayRefund payRefund = new SecapiPayRefund();
payRefund.setAppid(APP_ID);
payRefund.setMch_id(MCH_ID);
payRefund.setNonce_str(UUID.randomUUID().toString().replaceAll("-", ""));
payRefund.setOut_trade_no(orderId);// 支付订单号
payRefund.setOut_refund_no(orderId);// 退款单号
payRefund.setTotal_fee(refundAmount);// 原订单金额,单位:分;
payRefund.setRefund_fee(refundAmount);// 退款订单金额,单位:分;
SecapiPayRefundResult refundResult = PayMchAPI.secapiPayRefund(payRefund, API_KEY);
// 微信支付退款接口返回数据验签;
if (refundResult.getSign_status() != null && refundResult.getSign_status()) {
// 退款信息提交成功;
if ("SUCCESS".equals(refundResult.getReturn_code())) {
return true;
} else {
System.out.println("微信退款接口(getResult_code):" + refundResult.getResult_code());
}
}
return false;
}
// 微信退款结果查询
public static boolean refundQuery(String orderId) {
Refundquery refundquery = new Refundquery();
refundquery.setAppid(APP_ID);
refundquery.setMch_id(MCH_ID);
refundquery.setNonce_str(UUID.randomUUID().toString().replaceAll("-", ""));
refundquery.setOut_refund_no(orderId);
RefundqueryResult payRefundquery = PayMchAPI.payRefundquery(refundquery, API_KEY);
if (null != payRefundquery && payRefundquery.getSign_status()) {
if ("SUCCESS".equals(payRefundquery.getReturn_code())) {
return true;
} else {
System.out.println("微信退款查询接口(result_code):" + payRefundquery.getResult_code());
}
}
return false;
}
}
注意上面的金额做好处理,特别double类型,处理不好就是个坑
// 微信支付
@RequestMapping(value = "/wechatPay")
@ResponseBody
public ApiJsonRes h5Pay(HttpServletRequest request, HttpServletResponse response, String id) {
Map<String, Object> result = new HashMap<>();
ApiJsonRes apiJsonRes = new ApiJsonRes("0", "");
Order findoneById = orderService.findoneById(id);
if (null == findoneById) {
apiJsonRes.setApiResCodeDesc("无此订单");
return apiJsonRes;
}
result.put("success", false);
try {
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
String goodsName = findoneById.getGoodsName();
orderRequest.setBody(goodsName);
orderRequest.setOutTradeNo(id);
// 商品支付金额
Integer salePrice = findoneById.getSalePrice();
String total_fee = salePrice .toString().trim();
// 金额做处理,否则容易报错
String string = new BigDecimal(total_fee).multiply(new BigDecimal(100)).toString().split("\\.")[0];
orderRequest.setTotalFee(Integer.valueOf(string));
orderRequest.setSpbillCreateIp(HttpUtil.getRealIp(request));
// H5支付标识为MWEB
orderRequest.setTradeType("MWEB");
orderRequest.setSceneInfo("{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"" + WeixinPayUtils.REDIRECT_DOMAIN
+ "\",\"wap_name\": \"" + goodsName + "\"}}");
orderRequest.setSignType("MD5");
// 签名创建
Map<String, String> packageParams = new HashMap<>();
packageParams.put("appid", WeixinPayUtils.APP_ID);
packageParams.put("mch_id", WeixinPayUtils.MCH_ID);
packageParams.put("nonce_str", UUID.randomUUID().toString().replace("-", ""));
packageParams.put("signType", orderRequest.getSignType());
String sign = SignUtils.createSign(packageParams, "MD5", WeixinPayUtils.API_KEY, false);
orderRequest.setSign(sign);
WxPayMwebOrderResult orderResult = WeixinPayUtils.wxPayService().createOrder(orderRequest);
String mwebUrl = orderResult.getMwebUrl();
// response.sendRedirect(mwebUrl);
result.put("success", true);
apiJsonRes.setApiResCode("200");
apiJsonRes.setData(mwebUrl);
return apiJsonRes;
} catch (Exception e) {
result.put("errormsg", e.getMessage());
}
return apiJsonRes;
}
可以先写自己的业务代码,再去支付
@RequestMapping("/ymlwx")
public void weixin_notify(HttpServletRequest request, HttpServletResponse response, ModelMap model)
throws Exception {
String xmlMsg = readData(request);
@SuppressWarnings("unchecked")
Map<String, Object> params = XMLUtil.doXMLParse(xmlMsg);
// 微信支付订单号
String transaction_id = (String) params.get("transaction_id");
// 商户订单号
String out_trade_no = (String) params.get("out_trade_no");
try {
// 过滤空 设置 TreeMap
SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
Iterator<String> it = params.keySet().iterator();
while (it.hasNext()) {
String parameter = (String) it.next();
String parameterValue = params.get(parameter) + "";
String v = "";
if (null != parameterValue) {
v = parameterValue.trim();
}
packageParams.put(parameter, v);
}
// 查看回调参数
String resXml = "";
if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
// 支付成功之后写自己的业务代码
orderService.doCallback(out_trade_no, transaction_id);
mobileService.updateStatusById(out_trade_no, 2);
// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
} else {
model.put("sHtmlText", "支付失败");
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
+ "<return_msg><![CDATA[支付失败]]></return_msg>" + "</xml> ";
}
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(resXml.getBytes());
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static String readData(HttpServletRequest request) {
BufferedReader br = null;
try {
StringBuilder result = new StringBuilder();
br = request.getReader();
for (String line; (line = br.readLine()) != null;) {
if (result.length() > 0) {
result.append("\n");
}
result.append(line);
}
return result.toString();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (br != null)
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
才开始写博客,有什么遗漏的可以留言我