| | |
| | | package com.sandu.ximon.admin.pay.wx; |
| | | |
| | | import cn.dreampie.encription.EncriptionKit; |
| | | import cn.hutool.core.codec.Base64; |
| | | 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.hutool.crypto.SecureUtil; |
| | | import cn.hutool.http.HttpUtil; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; |
| | |
| | | import com.github.binarywang.wxpay.config.WxPayConfig; |
| | | import com.github.binarywang.wxpay.constant.WxPayConstants; |
| | | import com.github.binarywang.wxpay.exception.WxPayException; |
| | | import com.github.binarywang.wxpay.service.WxPayService; |
| | | import com.sandu.common.execption.BusinessException; |
| | | import com.sandu.common.util.IpUtil; |
| | | import com.sandu.common.util.SpringContextHolder; |
| | | import com.sandu.ximon.admin.dto.wxquerydto.WxOrderDto; |
| | | import com.sandu.ximon.admin.pay.wxpay.UsrWxPayConfigService; |
| | | import com.sandu.ximon.admin.service.C3mOrderService; |
| | | import com.sandu.ximon.dao.domain.C3mOrder; |
| | | import com.sandu.ximon.dao.domain.WxConfigEntity; |
| | | import com.sandu.ximon.dao.enums.OrderStatus; |
| | | 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.*; |
| | |
| | | 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_PAY_CALLBACK_URL = "http://112.74.63.130:20017/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; |
| | | |
| | | |
| | | |
| | | /** |
| | |
| | | */ |
| | | @SuppressWarnings("rawtypes") |
| | | private String createSign(String Key, SortedMap<Object, Object> parameters) { |
| | | |
| | | StringBuffer sb = new StringBuffer(); |
| | | Set es = parameters.entrySet();// 所有参与传参的参数按照accsii排序(升序) |
| | | Iterator it = es.iterator(); |
| | | while (it.hasNext()) { |
| | | Map.Entry entry = (Map.Entry) it.next(); |
| | | for (Object e : es) { |
| | | Map.Entry entry = (Map.Entry) e; |
| | | String k = (String) entry.getKey(); |
| | | Object v = entry.getValue(); |
| | | if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { |
| | |
| | | } |
| | | sb.append("key=" + Key); |
| | | System.out.println("字符串拼接后是:" + sb.toString()); |
| | | String sign = EncriptionKit.encrypt(sb.toString()).toUpperCase(); |
| | | return sign; |
| | | return SecureUtil.md5(sb.toString()).toUpperCase(); |
| | | // 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 WxPayOrderNotifyResult parseOrderNotifyResult(WxPayService wxPayService, String xmlData) { |
| | | try { |
| | | return wxPayService.parseOrderNotifyResult(xmlData); |
| | | } catch (WxPayException e) { |
| | |
| | | |
| | | /** |
| | | * 退款 |
| | | * |
| | | * @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); |
| | | public boolean refund(C3mOrder c3mOrder) { |
| | | |
| | | // 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()); |
| | | // } |
| | | // |
| | | |
| | | |
| | | WxConfigEntity wxConfig = wxPayConfigService.getConfigByPoleId(c3mOrder.getPoleId()); |
| | | |
| | | if (wxConfig.getKeyPath() == null && wxConfig.getKeyPath().isEmpty()) { |
| | | throw new BusinessException("微信证书不存在,无法进行退款"); |
| | | } |
| | | //设置微信支付参数 |
| | | 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(wxConfig.getKeyPath())); |
| | | wxPayService.setConfig(payConfig); |
| | | |
| | | |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); |
| | | String refundNo = sdf.format(new Date()); |
| | | WxPayRefundRequest refundRequest = new WxPayRefundRequest(); |
| | | //退款金额不能大于订单总金额 |
| | | if (refundAmount > totalAmount) { |
| | | if (c3mOrder.getRefundAmount() > c3mOrder.getTotalAmount()) { |
| | | throw new BusinessException("退款金额不能大于订单总金额"); |
| | | } |
| | | refundRequest.setOutTradeNo(outTradeNo); |
| | | System.out.println("" + c3mOrder.getRefundAmount()); |
| | | refundRequest.setOutTradeNo(c3mOrder.getOutTradeNo()); |
| | | refundRequest.setOutRefundNo(refundNo); |
| | | refundRequest.setTotalFee(Integer.valueOf(parseWxAmount((totalAmount + "")))); |
| | | refundRequest.setRefundFee(Integer.valueOf(parseWxAmount((refundAmount + "")))); |
| | | refundRequest.setTotalFee(Integer.valueOf(parseWxAmount((c3mOrder.getTotalAmount() + "")))); |
| | | refundRequest.setRefundFee(Integer.valueOf(parseWxAmount((c3mOrder.getRefundAmount() + "")))); |
| | | try { |
| | | WxPayRefundResult wxPayRefundResult = wxPayService.refund(refundRequest); |
| | | if (WxPayConstants.ResultCode.SUCCESS.equals(wxPayRefundResult.getResultCode())) { |
| | | c3mOrder.setOrderStatus(OrderStatus.REFUND.getStatus()); |
| | | c3mOrder.setChargingStates(1); |
| | | SpringContextHolder.getBean(C3mOrderService.class).updateById(c3mOrder); |
| | | return true; |
| | | } else { |
| | | log.error("微信退款失败,{}", wxPayRefundResult.getErrCodeDes()); |
| | |
| | | * @return |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public SortedMap<Object, Object> miniAppPay(String body, |
| | | String orderId, int totalFee, Long poleId) { |
| | | public SortedMap<Object, Object> miniAppPay(HttpServletRequest request, String body, String orderId, int totalFee, Long poleId, String wxCode) throws WxErrorException { |
| | | WxConfigEntity wxConfig = wxPayConfigService.getConfigByPoleId(poleId); |
| | | wxConfig.setMchId(wxConfig.getMchId().trim()); |
| | | |
| | | //设置微信支付参数 |
| | | WxPayConfig payConfig = new WxPayConfig(); |
| | | payConfig.setAppId(StringUtils.trimToNull(wxConfig.getAppid())); |
| | | |
| | | payConfig.setAppId(StringUtils.trimToNull(wxConfig.getAppappid())); |
| | | payConfig.setMchId(StringUtils.trimToNull(wxConfig.getMchId())); |
| | | payConfig.setMchKey(StringUtils.trimToNull(wxConfig.getPrivateKey())); |
| | | payConfig.setSubAppId(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("otiM54x_hc_5gbhMY5aZxo7UByNo"); |
| | | wxPayUnifiedOrderRequest.setOpenid(wxCode); |
| | | |
| | | |
| | | wxPayUnifiedOrderRequest.setSignType(WxPayConstants.SignType.MD5); |
| | | wxPayUnifiedOrderRequest.setSpbillCreateIp(IpUtil.getRealIp()); |
| | | wxPayUnifiedOrderRequest.setSpbillCreateIp(IpUtil.getIpAddr(request)); |
| | | wxPayUnifiedOrderRequest.setNotifyUrl(WECHAT_ORDER_PAY_CALLBACK_URL); |
| | | wxPayUnifiedOrderRequest.setTradeType(WxPayConstants.TradeType.JSAPI); |
| | | System.out.println("-----------" + wxPayUnifiedOrderRequest); |
| | |
| | | String time = String.valueOf(System.currentTimeMillis() / 1000); |
| | | if (WxPayConstants.ResultCode.SUCCESS.equals(wxPayUnifiedOrderResult.getResultCode())) { |
| | | SortedMap<Object, Object> parameters = new TreeMap<>(); |
| | | parameters.put("appid", wxPayUnifiedOrderResult.getAppid()); |
| | | parameters.put("appId", wxPayUnifiedOrderResult.getAppid()); |
| | | |
| | | parameters.put("noncestr", wxPayUnifiedOrderResult.getNonceStr()); // 随机字符串 |
| | | parameters.put("partnerid", wxConfig.getMchId()); // 商户id |
| | | parameters.put("nonceStr", wxPayUnifiedOrderResult.getNonceStr()); // 随机字符串 |
| | | // parameters.put("partnerid", wxConfig.getMchId()); // 商户id |
| | | |
| | | parameters.put("signType", WxPayConstants.SignType.MD5); |
| | | // parameters.put("out_trade_no", orderId);//商户订单号 |
| | | parameters.put("prepayid", wxPayUnifiedOrderResult.getPrepayId()); |
| | | parameters.put("package", "Sign=WXPay"); |
| | | parameters.put("timestamp", time); |
| | | // parameters.put("prepayid", wxPayUnifiedOrderResult.getPrepayId()); |
| | | parameters.put("package", "prepay_id=" + wxPayUnifiedOrderResult.getPrepayId()); |
| | | parameters.put("timeStamp", time); |
| | | |
| | | String sign = createSign(wxConfig.getPrivateKey(), parameters); |
| | | |
| | | //hashMap.put("paySign", wechatSign); |
| | | parameters.put("Sign", sign); |
| | | parameters.put("paySign", sign); |
| | | return parameters; |
| | | } else { |
| | | log.error("微信支付失败,{}", wxPayUnifiedOrderResult.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(); |
| | | } |
| | | |
| | | } |