package com.sandu.ximon.admin.pay.wx; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl; import cn.dreampie.encription.EncriptionKit; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSON; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest; import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; import com.github.binarywang.wxpay.bean.result.WxPayRefundResult; import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult; import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.constant.WxPayConstants; import com.github.binarywang.wxpay.exception.WxPayException; import com.sandu.common.execption.BusinessException; import com.sandu.common.util.IpUtil; import com.sandu.ximon.admin.dto.wxquerydto.WxOrderDto; import com.sandu.ximon.admin.pay.wxpay.UsrWxPayConfigService; import com.sandu.ximon.dao.domain.WxConfigEntity; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.error.WxErrorException; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.HttpServletRequest; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.*; /** * @author chenjiantian * @date 2021/8/12 11:26 */ @Service @Slf4j @AllArgsConstructor public class WxFastPayService { private final com.github.binarywang.wxpay.service.WxPayService wxPayService; public static final String WECHAT_ORDER_PAY_CALLBACK_URL = "http://49.235.239.118:20012/callback/pay/wechatCallback"; //微信订单状态查询 public static final String WECHAT_ORDER_QUETY_URL = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/"; public static final String WECHAT_ORDER_QUETY = "?mchid="; private final UsrWxPayConfigService wxPayConfigService; /** * 微信订单状态查询 * * @param poleId * @param outTradeNo * @return */ public boolean WxOrderQuery(Long poleId, String outTradeNo) { WxConfigEntity wxConfig = wxPayConfigService.getConfigByPoleId(poleId); if (wxConfig == null) { throw new BusinessException("获取微信支付配置失败"); } String s = HttpUtil.get(WECHAT_ORDER_QUETY_URL + outTradeNo + WECHAT_ORDER_QUETY + wxConfig.getMchId());//WxOrderDto WxOrderDto wxOrderDto = JSON.parseObject(s, WxOrderDto.class); if (("SUCCESS").equals(wxOrderDto.getTrade_state())) { return true; } return false; } /** * @param parameters * @return */ @SuppressWarnings("rawtypes") private String createSign(String Key, SortedMap parameters) { StringBuffer sb = new StringBuffer(); Set es = parameters.entrySet();// 所有参与传参的参数按照accsii排序(升序) 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=" + Key); System.out.println("字符串拼接后是:" + sb.toString()); String sign = EncriptionKit.encrypt(sb.toString()).toUpperCase(); return sign; } public WxPayOrderNotifyResult parseOrderNotifyResult(String xmlData) { try { return wxPayService.parseOrderNotifyResult(xmlData); } catch (WxPayException e) { e.printStackTrace(); throw new BusinessException("解析回调结果失败," + e.getErrCodeDes()); } } public WxPayRefundNotifyResult parseRefundNotifyResult(String xmlData) { try { return wxPayService.parseRefundNotifyResult(xmlData); } catch (WxPayException e) { e.printStackTrace(); throw new BusinessException("解析回调结果失败," + e.getErrCodeDes()); } } /** * 订单退款 只能退款一次 * * @param orderId * @param refundFee * @param callbackUrl * @return */ public boolean refundOrder(String orderId, String refundSn, Integer refundFee, String callbackUrl) { WxPayRefundRequest refundRequest = new WxPayRefundRequest(); refundRequest.setOutTradeNo(orderId); refundRequest.setOutRefundNo(refundSn); refundRequest.setRefundFee(refundFee); refundRequest.setTotalFee(refundFee); refundRequest.setNotifyUrl(callbackUrl); try { WxPayRefundResult wxPayRefundResult = wxPayService.refund(refundRequest); if (WxPayConstants.ResultCode.SUCCESS.equals(wxPayRefundResult.getResultCode())) { return true; } else { log.error("微信退款失败,{}", wxPayRefundResult.getErrCodeDes()); throw new BusinessException("微信退款失败," + wxPayRefundResult.getErrCodeDes()); } } catch (WxPayException e) { log.error("微信退款失败,{}", e.getErrCodeDes()); throw new BusinessException("微信退款失败," + e.getErrCodeDes()); } } /** * 退款 * * @param totalAmount * @param refundAmount * @param outTradeNo * @param poleId * @return */ @Transactional(rollbackFor = Exception.class) public boolean refund(Double totalAmount, Double refundAmount, String outTradeNo, Long poleId) { WxConfigEntity wxConfig = UsrWxPayConfigService.getBean().getConfigByPoleId(poleId); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); String refundNo = sdf.format(new Date()); WxPayRefundRequest refundRequest = new WxPayRefundRequest(); //退款金额不能大于订单总金额 if (refundAmount > totalAmount) { throw new BusinessException("退款金额不能大于订单总金额"); } refundRequest.setOutTradeNo(outTradeNo); refundRequest.setOutRefundNo(refundNo); refundRequest.setTotalFee(Integer.valueOf(parseWxAmount((totalAmount + "")))); refundRequest.setRefundFee(Integer.valueOf(parseWxAmount((refundAmount + "")))); try { WxPayRefundResult wxPayRefundResult = wxPayService.refund(refundRequest); if (WxPayConstants.ResultCode.SUCCESS.equals(wxPayRefundResult.getResultCode())) { return true; } else { log.error("微信退款失败,{}", wxPayRefundResult.getErrCodeDes()); throw new BusinessException("微信退款失败," + wxPayRefundResult.getErrCodeDes()); } } catch (WxPayException e) { log.error("微信退款失败,{}", e.getErrCodeDes()); throw new BusinessException("微信退款失败," + e.getErrCodeDes()); } } /** * 转换为微信金额(分) * * @param normalAmount 0.01元 * @return */ public static String parseWxAmount(String normalAmount) { // 保留2位小数 double totalAmountDouble = Double.parseDouble(new DecimalFormat("#.00").format( Double.parseDouble(normalAmount))); String amount = (totalAmountDouble * 100) + ""; amount = amount.substring(0, amount.indexOf(".")); return amount; } /** * 小程序支付 微信 * * @param body * @param orderId * @param totalFee * @param poleId * @return */ @Transactional(rollbackFor = Exception.class) public SortedMap miniAppPay(HttpServletRequest request, String body, String orderId, int totalFee, Long poleId, String wxCode) throws WxErrorException { WxConfigEntity wxConfig = wxPayConfigService.getConfigByPoleId(poleId); //设置微信支付参数 WxPayConfig payConfig = new WxPayConfig(); payConfig.setAppId(StringUtils.trimToNull(wxConfig.getAppappid())); payConfig.setMchId(StringUtils.trimToNull(wxConfig.getMchId())); payConfig.setMchKey(StringUtils.trimToNull(wxConfig.getPrivateKey())); payConfig.setSubAppId(StringUtils.trimToNull(null)); payConfig.setSubMchId(StringUtils.trimToNull(null)); payConfig.setKeyPath(StringUtils.trimToNull(null)); wxPayService.setConfig(payConfig); //设置微信同一订单请求 WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest(); wxPayUnifiedOrderRequest.setBody(body); wxPayUnifiedOrderRequest.setOutTradeNo(orderId); wxPayUnifiedOrderRequest.setTotalFee(totalFee); wxPayUnifiedOrderRequest.setOpenid(wxCode); wxPayUnifiedOrderRequest.setSignType(WxPayConstants.SignType.MD5); wxPayUnifiedOrderRequest.setSpbillCreateIp(IpUtil.getIpAddr(request)); wxPayUnifiedOrderRequest.setNotifyUrl(WECHAT_ORDER_PAY_CALLBACK_URL); wxPayUnifiedOrderRequest.setTradeType(WxPayConstants.TradeType.JSAPI); System.out.println("-----------" + wxPayUnifiedOrderRequest); try { WxPayUnifiedOrderResult wxPayUnifiedOrderResult = wxPayService.unifiedOrder(wxPayUnifiedOrderRequest); String time = String.valueOf(System.currentTimeMillis() / 1000); if (WxPayConstants.ResultCode.SUCCESS.equals(wxPayUnifiedOrderResult.getResultCode())) { SortedMap parameters = new TreeMap<>(); parameters.put("appid", wxPayUnifiedOrderResult.getAppid()); // parameters.put("noncestr", wxPayUnifiedOrderResult.getNonceStr()); // 随机字符串 parameters.put("partnerid", wxConfig.getMchId()); // 商户id // parameters.put("out_trade_no", orderId);//商户订单号 parameters.put("prepayid", wxPayUnifiedOrderResult.getPrepayId()); // parameters.put("package", "Sign=WXPay"); // parameters.put("timestamp", time); String sign = createSign(wxConfig.getPrivateKey(), parameters); //hashMap.put("paySign", wechatSign); parameters.put("Sign", sign); return parameters; } else { log.error("微信支付失败,{}", wxPayUnifiedOrderResult.getErrCodeDes()); throw new BusinessException("微信支付失败," + wxPayUnifiedOrderResult); } } catch (WxPayException e) { log.error("微信支付失败,{}", e.getErrCodeDes()); throw new BusinessException("微信支付失败," + e.getErrCodeDes()); } } public WxMaService getWxMaService(WxConfigEntity wxConfig) { if (wxConfig == null) { throw new BusinessException("找不到微信配置"); } WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl(); config.setAppid(wxConfig.getAppappid()); config.setSecret(wxConfig.getAppSecret()); WxMaService service = new WxMaServiceImpl(); service.setWxMaConfig(config); return service; } public String getOpenId(Long poleId, String wxCode) throws WxErrorException { WxConfigEntity userConfig = wxPayConfigService.getConfigByPoleId(poleId); if (userConfig == null) { throw new BusinessException("找不到微信配置"); } WxMaJscode2SessionResult sessionInfo = this.getWxMaService(userConfig).getUserService().getSessionInfo(wxCode); return sessionInfo.getOpenid(); } }