package com.xzx.gc.pay.service;
|
|
|
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.date.DateUtil;
|
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
|
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
|
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
|
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
|
import com.github.binarywang.wxpay.service.WxPayService;
|
import com.xzx.gc.common.Result;
|
import com.xzx.gc.common.constant.Constants;
|
import com.xzx.gc.common.constant.PayEnum;
|
import com.xzx.gc.common.dto.log.PayInfoLog;
|
import com.xzx.gc.common.exception.wx.WxPayNotifyResponseException;
|
import com.xzx.gc.common.utils.BusinessUtil;
|
import com.xzx.gc.common.utils.ExceptionUtils;
|
import com.xzx.gc.common.utils.RedisUtil;
|
import com.xzx.gc.common.utils.wxpay.WXPayUtil;
|
import com.xzx.gc.entity.AccountInfo;
|
import com.xzx.gc.entity.PayInfo;
|
import com.xzx.gc.entity.PayWxRecord;
|
import com.xzx.gc.pay.dto.PayParamDTO;
|
import com.xzx.gc.pay.dto.PayResultDTO;
|
import com.xzx.gc.pay.mapper.PayInfoMapper;
|
import com.xzx.gc.pay.mapper.PayWxRecordMapper;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import javax.servlet.http.HttpServletRequest;
|
import java.util.HashMap;
|
import java.util.Map;
|
|
@Service
|
@Transactional
|
@Slf4j
|
public class WeiXinService {
|
@Autowired
|
private WxPayService wxPayService;
|
|
|
@Autowired
|
private PayService payService;
|
|
@Autowired
|
private PayInfoMapper payInfoMapper;
|
|
@Autowired
|
private HttpServletRequest request;
|
|
@Autowired
|
private RedisUtil redisUtil;
|
|
@Autowired
|
private PayWxRecordMapper payWxRecordMapper;
|
|
@Autowired
|
private PayInfoLogService payInfoLogService;
|
|
@Autowired
|
private BusinessUtil businessUtil;
|
|
@Autowired
|
private AccountService accountService;
|
|
/**
|
* 生成小程序支付签名
|
* @param payResultDTO
|
* @return
|
* @throws Exception
|
*/
|
private String geWebSign(PayResultDTO payResultDTO) throws Exception {
|
Map<String, String> packageParams = new HashMap<String, String>();
|
packageParams.put("appId", wxPayService.getConfig().getAppId());
|
packageParams.put("timeStamp", payResultDTO.getTimeStamp());
|
packageParams.put("nonceStr", payResultDTO.getNonce());
|
packageParams.put("package", payResultDTO.getPrepayId());
|
packageParams.put("signType", "MD5");
|
String packageSign = WXPayUtil.generateSignature(packageParams, wxPayService.getConfig().getMchKey());
|
return packageSign;
|
}
|
|
/**
|
* 生成安卓APP签名
|
* @param payResultDTO
|
* @return
|
* @throws Exception
|
*/
|
private String geAnroidSign(PayResultDTO payResultDTO) throws Exception {
|
Map<String, String> packageParams = new HashMap<String, String>();
|
packageParams.put("appid", wxPayService.getConfig().getAppId());
|
packageParams.put("partnerid", wxPayService.getConfig().getMchId());
|
packageParams.put("prepayid", payResultDTO.getPrepayId());
|
packageParams.put("package", payResultDTO.getExtra());
|
packageParams.put("noncestr", payResultDTO.getNonce());
|
packageParams.put("timestamp", payResultDTO.getTimeStamp());
|
String packageSign = WXPayUtil.generateSignature(packageParams, wxPayService.getConfig().getMchKey());
|
return packageSign;
|
}
|
|
/**
|
* 微信预支付
|
*
|
* @param wxPayUnifiedOrderRequest
|
* @param payParamDTO
|
* @return
|
*/
|
public Result<PayResultDTO> pay(WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest, PayParamDTO payParamDTO) {
|
Result<PayResultDTO> res=new Result<>();
|
PayResultDTO payResultDTO = new PayResultDTO();
|
try {
|
String userId = request.getHeader("userId");
|
|
WxPayUnifiedOrderResult result = wxPayService.unifiedOrder(wxPayUnifiedOrderRequest);
|
PayInfo payInfo = new PayInfo();
|
payInfo.setOrderId(result.getPrepayId());
|
payInfo.setCreateUserId(userId);
|
|
if(businessUtil.isApp(request.getHeader("clientType"))){
|
//需要服务费
|
payInfo.setMoney(businessUtil.changeMoney(payParamDTO.getMoney()));
|
payInfo.setFee(businessUtil.changeMoney(payParamDTO.getFee()));
|
}else {
|
payInfo.setMoney(payParamDTO.getTotalFee().toString());
|
}
|
|
AccountInfo accountInfo1 =accountService.findByUserId(userId);
|
|
if (accountInfo1 == null) {
|
return Result.error(-1, "账户不存在");
|
}
|
|
payInfo.setAccountId(accountInfo1.getAccountId());
|
payInfo.setPayType(PayEnum.待支付.getValue());
|
payInfo.setOpenId(payParamDTO.getOpenid());
|
payInfo.setStatus(PayEnum.充值.getValue());
|
payInfo.setPayOrderId(payParamDTO.getOutTradeNo());
|
payService.addPay(payInfo);
|
|
PayInfoLog payInfoLog=new PayInfoLog();
|
BeanUtil.copyProperties(payInfo,payInfoLog);
|
payInfoLog.setAccount(accountInfo1.getAccountName());
|
payInfoLog.setAccountClass(PayEnum.微信.getValue());
|
payInfoLog.setPayType(PayEnum.充值交易.getValue());
|
payInfoLogService.add(payInfoLog);
|
|
payResultDTO.setNonce(payParamDTO.getNonceStr());
|
payResultDTO.setTimeStamp(Convert.toStr(DateUtil.currentSeconds()));
|
payResultDTO.setMchId(wxPayService.getConfig().getMchId());
|
|
if(businessUtil.isWeb(payParamDTO.getClientType())){
|
payResultDTO.setPrepayId("prepay_id="+result.getPrepayId());
|
payResultDTO.setSign(geWebSign(payResultDTO));
|
}else if(businessUtil.isApp(payParamDTO.getClientType())){
|
payResultDTO.setPrepayId(result.getPrepayId());
|
payResultDTO.setExtra("Sign=WXPay");
|
payResultDTO.setSign(geAnroidSign(payResultDTO));
|
}
|
payResultDTO.setAppId(wxPayService.getConfig().getAppId());
|
payResultDTO.setPayOrderId(payInfo.getPayOrderId());
|
res.setData(payResultDTO);
|
return res;
|
} catch (Exception e) {
|
ExceptionUtils.err("微信预支付失败",e);
|
}
|
return res;
|
}
|
|
/**
|
* 微信回调
|
*
|
*/
|
public String payBack(String xmlResult) {
|
String payOrderId="";
|
boolean lock=false;
|
try {
|
//记录微信回调日志
|
record(xmlResult);
|
WxPayOrderNotifyResult result = wxPayService.parseOrderNotifyResult(xmlResult);
|
payOrderId = result.getOutTradeNo();
|
// 锁+去重
|
if(redisUtil.setnx(Constants.REDIS_PAY_KEY+"wx:payback:"+payOrderId,payOrderId)) {
|
lock=true;
|
PayInfo payInfo = payInfoMapper.selectByPrimaryKey(payOrderId);
|
if (payInfo != null) {
|
if (payInfo.getStatus().equals(PayEnum.已支付.getValue())) {
|
return WxPayNotifyResponse.success("处理成功!");
|
}else{
|
Map map = new HashMap();
|
map.put("userId", payInfo.getCreateUserId());
|
map.put("money", payInfo.getMoney());
|
map.put("status", PayEnum.已支付.getValue());
|
map.put("payOrderId", payInfo.getPayOrderId());
|
map.put("fee",payInfo.getFee());
|
payService.webChatRechargeCallback(map);
|
}
|
}
|
}
|
return WxPayNotifyResponse.success("处理成功!");
|
} catch (Exception e) {
|
log.error("微信回调失败,订单:"+payOrderId, e);
|
throw new WxPayNotifyResponseException(WxPayNotifyResponse.fail(e.getMessage()));
|
}finally {
|
if(lock) {
|
redisUtil.del(Constants.REDIS_PAY_KEY+"wx:payback:"+payOrderId);
|
}
|
}
|
}
|
|
|
private void record(String xmlResult){
|
WxPayOrderNotifyResult res= WxPayOrderNotifyResult.fromXML(xmlResult);
|
PayWxRecord payWxRecord=new PayWxRecord();
|
BeanUtils.copyProperties(res,payWxRecord);
|
payWxRecord.setCreateTime(DateUtil.now());
|
payWxRecordMapper.insertSelective(payWxRecord);
|
}
|
|
|
// @Scheduled(cron = "${wx.pay.cron}")
|
// @Async
|
// public void syncPay(){
|
// log.trace("********定时修复支付订单开始【每1分钟执行1次】*********");
|
// Example example=new Example(PayInfo.class);
|
// Example.Criteria criteria = example.createCriteria();
|
// criteria.andEqualTo("payType",PayEnum.充值.getValue());
|
// criteria.andEqualTo("status",PayEnum.待支付.getValue());
|
// criteria.andCondition("IFNULL(check_num,0)<2");
|
// criteria.andCondition("to_days(create_time) = to_days(now())");
|
// List<PayInfo> payInfos = payInfoMapper.selectByExample(example);
|
//
|
// if(CollUtil.isNotEmpty(payInfos)){
|
// for (PayInfo payInfo : payInfos) {
|
// String createTime = payInfo.getCreateTime();
|
// String date=DateUtil.now();
|
// long between = DateUtil.between(DateUtil.parse(createTime,DateUtils.DATE_FORMAT_YMDHMS), DateUtil.parse(date,DateUtils.DATE_FORMAT_YMDHMS), DateUnit.MINUTE);
|
// //3分钟后进行查询
|
// if(between<3){
|
// continue;
|
// }
|
// String payOrderId = payInfo.getPayOrderId();
|
// Integer checkNum = payInfo.getCheckNum();
|
// if(checkNum==null){
|
// checkNum=0;
|
// }
|
// WxPayOrderQueryResult wxPayOrderQueryResult = null;
|
// boolean lock=false;
|
// try {
|
// wxPayOrderQueryResult = wxPayService.queryOrder(null, payOrderId);
|
// String returnCode = wxPayOrderQueryResult.getReturnCode();
|
// String resultCode = wxPayOrderQueryResult.getResultCode();
|
// if("SUCCESS".equals(returnCode)&&"SUCCESS".equals(resultCode)){
|
// //SUCCESS—支付成功,REFUND—转入退款,NOTPAY—未支付,CLOSED—已关闭,REVOKED—已撤销(刷卡支付),USERPAYING--用户支付中,PAYERROR--支付失败(其他原因,如银行返回失败)
|
// String tradeState = wxPayOrderQueryResult.getTradeState();
|
// log.trace("充值交易流水号:{},交易状态:{}",payOrderId,tradeState);
|
// if("SUCCESS".equals(tradeState)){
|
// // 锁+去重
|
// if(redisUtil.setnx(Constants.REDIS_PAY_KEY+"wx:payback:"+payOrderId,payOrderId)) {
|
// lock=true;
|
// PayInfo payInfo2 = payInfoMapper.selectByPrimaryKey(payOrderId);
|
// if (payInfo2 != null) {
|
// if (payInfo2.getStatus().equals(PayEnum.已支付.getValue())) {
|
// continue;
|
// }else{
|
// Map map = new HashMap();
|
// map.put("userId", payInfo2.getCreateUserId());
|
// map.put("money", payInfo2.getMoney());
|
// map.put("status", PayEnum.已支付.getValue());
|
// map.put("payOrderId", payInfo2.getPayOrderId());
|
// map.put("fee", payInfo2.getFee());
|
// payService.webChatRechargeCallback(map);
|
// log.info("支付订单:{}已自动修复成功",payOrderId);
|
// }
|
// }
|
// }
|
// }else{
|
// PayInfo payInfo2=new PayInfo();
|
// payInfo2.setPayOrderId(payInfo.getPayOrderId());
|
// checkNum=2;
|
// payInfo2.setCheckNum(checkNum);
|
// payInfoMapper.updateByPrimaryKeySelective(payInfo2);
|
// }
|
// }
|
// } catch (WxPayException e) {
|
// log.warn("主动调用微信支付查询出现异常");
|
// PayInfo payInfo2=new PayInfo();
|
// payInfo2.setPayOrderId(payInfo.getPayOrderId());
|
// checkNum=2;
|
// payInfo2.setCheckNum(checkNum);
|
// payInfoMapper.updateByPrimaryKeySelective(payInfo2);
|
// }finally {
|
// if(lock) {
|
// redisUtil.del(Constants.REDIS_PAY_KEY+"wx:payback:"+payOrderId);
|
// }
|
// }
|
// }
|
// }
|
// log.trace("********定时修复支付订单完成【每3分钟执行1次】*********");
|
//
|
// }
|
|
/**
|
* 修复支付
|
* @param payOrderId
|
*/
|
public Result payFix(String payOrderId) {
|
PayInfo payInfo2 = payInfoMapper.selectByPrimaryKey(payOrderId);
|
if (payInfo2 != null) {
|
if (payInfo2.getStatus().equals(PayEnum.已支付.getValue())) {
|
return Result.error("当前支付订单已支付成功");
|
}else{
|
Map map = new HashMap();
|
map.put("userId", payInfo2.getCreateUserId());
|
map.put("money", payInfo2.getMoney());
|
map.put("status", PayEnum.已支付.getValue());
|
map.put("payOrderId", payInfo2.getPayOrderId());
|
map.put("fee", payInfo2.getFee());
|
payService.webChatRechargeCallback(map);
|
return Result.success();
|
}
|
}
|
return Result.error("当前支付订单号不存在");
|
|
}
|
}
|