| @@ -180,7 +180,7 @@ public class WxPayController extends BaseController { | |||||
| xml = IOUtils.toString(request.getInputStream(), Charset.forName("UTF-8")); | xml = IOUtils.toString(request.getInputStream(), Charset.forName("UTF-8")); | ||||
| paramMap = WxPayment.xmlToMap(xml); | paramMap = WxPayment.xmlToMap(xml); | ||||
| logger.info("share wxpay, notify, param: " + xml ); | logger.info("share wxpay, notify, param: " + xml ); | ||||
| response = wxPayOrderService.notify(paramMap, EnumPayWay.PAY_WAY_WECHAT); | |||||
| response = wxPayOrderService.shareNotify(paramMap, EnumPayWay.PAY_WAY_WECHAT); | |||||
| logger.info("share wxpay, notify success, req : " + xml + ", resp: " + response.toString()); | logger.info("share wxpay, notify success, req : " + xml + ", resp: " + response.toString()); | ||||
| return response; | return response; | ||||
| } catch (BizMessageException e) { | } catch (BizMessageException e) { | ||||
| @@ -37,8 +37,8 @@ public class MqBaseConsumer { | |||||
| @Autowired | @Autowired | ||||
| private MqBaseProducer mqBaseProducer; | private MqBaseProducer mqBaseProducer; | ||||
| @Autowired | |||||
| private FmInsideNotifyPaySuccessMsgServiceImpl fmInsideNotifyPaySuccessMsgService; | |||||
| //@Autowired | |||||
| //private FmInsideNotifyPaySuccessMsgServiceImpl fmInsideNotifyPaySuccessMsgService; | |||||
| @Autowired | @Autowired | ||||
| private FmInsideNotifyRefundSuccessMsgServiceImpl fmInsideNotifyRefundSuccessMsgService; | private FmInsideNotifyRefundSuccessMsgServiceImpl fmInsideNotifyRefundSuccessMsgService; | ||||
| @Autowired | @Autowired | ||||
| @@ -89,11 +89,13 @@ public class MqBaseConsumer { | |||||
| // 内部消息 - c端登录 | // 内部消息 - c端登录 | ||||
| FmInsideCLoginMsg msg = (FmInsideCLoginMsg)JsonUtil.readValue(message,FmInsideCLoginMsg.class); | FmInsideCLoginMsg msg = (FmInsideCLoginMsg)JsonUtil.readValue(message,FmInsideCLoginMsg.class); | ||||
| fmInsideCouponVerifyMsgService.send(msg); | fmInsideCouponVerifyMsgService.send(msg); | ||||
| } else if(EnumMsgRecordType.INSIDE_NOTIFY_PAY_SUCCESS.getCode().equals(baseMsg.getMsgType())) { | |||||
| } | |||||
| //else if(EnumMsgRecordType.INSIDE_NOTIFY_PAY_SUCCESS.getCode().equals(baseMsg.getMsgType())) { | |||||
| // 内部消息 - 微信支付通知 | // 内部消息 - 微信支付通知 | ||||
| FmInsideNotifyPaySuccessMsg msg = (FmInsideNotifyPaySuccessMsg)JsonUtil.readValue(message,FmInsideNotifyPaySuccessMsg.class); | |||||
| fmInsideNotifyPaySuccessMsgService.send(msg); | |||||
| } else if(EnumMsgRecordType.INSIDE_NOTIFY_REFUND_SUCCESS.getCode().equals(baseMsg.getMsgType())) { | |||||
| //FmInsideNotifyPaySuccessMsg msg = (FmInsideNotifyPaySuccessMsg)JsonUtil.readValue(message,FmInsideNotifyPaySuccessMsg.class); | |||||
| //fmInsideNotifyPaySuccessMsgService.send(msg); | |||||
| //} | |||||
| else if(EnumMsgRecordType.INSIDE_NOTIFY_REFUND_SUCCESS.getCode().equals(baseMsg.getMsgType())) { | |||||
| // 内部消息 - 微信退款通知 | // 内部消息 - 微信退款通知 | ||||
| FmInsideNotifyRefundSuccessMsg msg = (FmInsideNotifyRefundSuccessMsg)JsonUtil.readValue(message,FmInsideNotifyRefundSuccessMsg.class); | FmInsideNotifyRefundSuccessMsg msg = (FmInsideNotifyRefundSuccessMsg)JsonUtil.readValue(message,FmInsideNotifyRefundSuccessMsg.class); | ||||
| fmInsideNotifyRefundSuccessMsgService.send(msg); | fmInsideNotifyRefundSuccessMsgService.send(msg); | ||||
| @@ -25,56 +25,56 @@ public class MsgReSendSchedule { | |||||
| @Autowired | @Autowired | ||||
| private MqBaseProducer mqBaseProducer; | private MqBaseProducer mqBaseProducer; | ||||
| @Scheduled(cron = "0 */5 * * * *?") // 每5分钟检查一次 | |||||
| //@Scheduled(cron = "0 */5 * * * *?") // 每5分钟检查一次 | |||||
| //@Scheduled(cron = "*/10 * * * * ?") // 测试10秒中一次 | //@Scheduled(cron = "*/10 * * * * ?") // 测试10秒中一次 | ||||
| public void msgReSend() { | public void msgReSend() { | ||||
| logger.info("消息重发开始..."); | |||||
| //消息重发 | |||||
| WxMsgRecord msgRecord = new WxMsgRecord(); | |||||
| msgRecord.setMsgStatus(EnumMsgRecordStatus.SEND_FAIL.getCode()); | |||||
| List<WxMsgRecord> recordList = wxMsgRecordService.findList(msgRecord); | |||||
| for (WxMsgRecord wxMsgRecord:recordList) { | |||||
| logger.info("消息重发:{}",wxMsgRecord.getMsgJson()); | |||||
| TenantEntity tenantEntity = wxMsgRecord.getTenantInfo(); | |||||
| try { | |||||
| if(EnumMsgRecordType.INSIDE_ORDER_SUCCESS.getCode().equals(wxMsgRecord.getMsgType())){ | |||||
| //内部消息 - 下订单成功 | |||||
| FmInsideOrderSuccessMsg msg = (FmInsideOrderSuccessMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),FmInsideOrderSuccessMsg.class); | |||||
| msg.setMsgType(wxMsgRecord.getMsgType()); | |||||
| msg.setReceiver(wxMsgRecord.getReceiver()); | |||||
| msg.updateTenantInfo(tenantEntity); | |||||
| mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); | |||||
| }else if(EnumMsgRecordType.INSIDE_COUPON_VERIFY.getCode().equals(wxMsgRecord.getMsgType())){ | |||||
| FmInsideCouponVerifyMsg msg = (FmInsideCouponVerifyMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),FmInsideCouponVerifyMsg.class); | |||||
| msg.setMsgType(wxMsgRecord.getMsgType()); | |||||
| msg.setReceiver(wxMsgRecord.getReceiver()); | |||||
| msg.updateTenantInfo(tenantEntity); | |||||
| mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); | |||||
| }else if(EnumMsgRecordType.INSIDE_C_LOGIN.getCode().equals(wxMsgRecord.getMsgType())){ | |||||
| FmInsideCLoginMsg msg = (FmInsideCLoginMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),FmInsideCLoginMsg.class); | |||||
| msg.setMsgType(wxMsgRecord.getMsgType()); | |||||
| msg.setReceiver(wxMsgRecord.getReceiver()); | |||||
| msg.updateTenantInfo(tenantEntity); | |||||
| mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); | |||||
| }else if(EnumMsgRecordType.INSIDE_NOTIFY_PAY_SUCCESS.getCode().equals(wxMsgRecord.getMsgType())){ | |||||
| FmInsideNotifyPaySuccessMsg msg = (FmInsideNotifyPaySuccessMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),FmInsideNotifyPaySuccessMsg.class); | |||||
| msg.setMsgType(wxMsgRecord.getMsgType()); | |||||
| msg.setReceiver(wxMsgRecord.getReceiver()); | |||||
| msg.updateTenantInfo(tenantEntity); | |||||
| mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); | |||||
| }else if(EnumMsgRecordType.INSIDE_NOTIFY_REFUND_SUCCESS.getCode().equals(wxMsgRecord.getMsgType())){ | |||||
| FmInsideNotifyRefundSuccessMsg msg = (FmInsideNotifyRefundSuccessMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),FmInsideNotifyRefundSuccessMsg.class); | |||||
| msg.setMsgType(wxMsgRecord.getMsgType()); | |||||
| msg.setReceiver(wxMsgRecord.getReceiver()); | |||||
| msg.updateTenantInfo(tenantEntity); | |||||
| mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| e.printStackTrace(); | |||||
| logger.error("消息重发错误:" + e.getMessage()); | |||||
| } | |||||
| } | |||||
| logger.info("消息重发结束..."); | |||||
| // logger.info("消息重发开始..."); | |||||
| // //消息重发 | |||||
| // WxMsgRecord msgRecord = new WxMsgRecord(); | |||||
| // msgRecord.setMsgStatus(EnumMsgRecordStatus.SEND_FAIL.getCode()); | |||||
| // List<WxMsgRecord> recordList = wxMsgRecordService.findList(msgRecord); | |||||
| // for (WxMsgRecord wxMsgRecord:recordList) { | |||||
| // logger.info("消息重发:{}",wxMsgRecord.getMsgJson()); | |||||
| // TenantEntity tenantEntity = wxMsgRecord.getTenantInfo(); | |||||
| // try { | |||||
| // if(EnumMsgRecordType.INSIDE_ORDER_SUCCESS.getCode().equals(wxMsgRecord.getMsgType())){ | |||||
| // //内部消息 - 下订单成功 | |||||
| // FmInsideOrderSuccessMsg msg = (FmInsideOrderSuccessMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),FmInsideOrderSuccessMsg.class); | |||||
| // msg.setMsgType(wxMsgRecord.getMsgType()); | |||||
| // msg.setReceiver(wxMsgRecord.getReceiver()); | |||||
| // msg.updateTenantInfo(tenantEntity); | |||||
| // mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); | |||||
| // }else if(EnumMsgRecordType.INSIDE_COUPON_VERIFY.getCode().equals(wxMsgRecord.getMsgType())){ | |||||
| // FmInsideCouponVerifyMsg msg = (FmInsideCouponVerifyMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),FmInsideCouponVerifyMsg.class); | |||||
| // msg.setMsgType(wxMsgRecord.getMsgType()); | |||||
| // msg.setReceiver(wxMsgRecord.getReceiver()); | |||||
| // msg.updateTenantInfo(tenantEntity); | |||||
| // mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); | |||||
| // }else if(EnumMsgRecordType.INSIDE_C_LOGIN.getCode().equals(wxMsgRecord.getMsgType())){ | |||||
| // FmInsideCLoginMsg msg = (FmInsideCLoginMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),FmInsideCLoginMsg.class); | |||||
| // msg.setMsgType(wxMsgRecord.getMsgType()); | |||||
| // msg.setReceiver(wxMsgRecord.getReceiver()); | |||||
| // msg.updateTenantInfo(tenantEntity); | |||||
| // mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); | |||||
| // }else if(EnumMsgRecordType.INSIDE_NOTIFY_PAY_SUCCESS.getCode().equals(wxMsgRecord.getMsgType())){ | |||||
| // FmInsideNotifyPaySuccessMsg msg = (FmInsideNotifyPaySuccessMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),FmInsideNotifyPaySuccessMsg.class); | |||||
| // msg.setMsgType(wxMsgRecord.getMsgType()); | |||||
| // msg.setReceiver(wxMsgRecord.getReceiver()); | |||||
| // msg.updateTenantInfo(tenantEntity); | |||||
| // mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); | |||||
| // }else if(EnumMsgRecordType.INSIDE_NOTIFY_REFUND_SUCCESS.getCode().equals(wxMsgRecord.getMsgType())){ | |||||
| // FmInsideNotifyRefundSuccessMsg msg = (FmInsideNotifyRefundSuccessMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),FmInsideNotifyRefundSuccessMsg.class); | |||||
| // msg.setMsgType(wxMsgRecord.getMsgType()); | |||||
| // msg.setReceiver(wxMsgRecord.getReceiver()); | |||||
| // msg.updateTenantInfo(tenantEntity); | |||||
| // mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); | |||||
| // } | |||||
| // } catch (Exception e) { | |||||
| // e.printStackTrace(); | |||||
| // logger.error("消息重发错误:" + e.getMessage()); | |||||
| // } | |||||
| // } | |||||
| // logger.info("消息重发结束..."); | |||||
| } | } | ||||
| @@ -30,7 +30,7 @@ import com.iformall.service.WxPayOrderService; | |||||
| import com.iformall.service.WxRefundOrderService; | import com.iformall.service.WxRefundOrderService; | ||||
| import com.iformall.service.helper.WxPayOrderServiceHelper; | import com.iformall.service.helper.WxPayOrderServiceHelper; | ||||
| import com.iformall.service.pay.PayServiceFactory; | import com.iformall.service.pay.PayServiceFactory; | ||||
| import com.iformall.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.utils.DateUtils; | import com.iformall.utils.DateUtils; | ||||
| @Component | @Component | ||||
| @@ -4,12 +4,14 @@ import com.baomidou.mybatisplus.annotation.TableName; | |||||
| import com.iformall.domain.po.base.TenantEntity; | import com.iformall.domain.po.base.TenantEntity; | ||||
| import lombok.Data; | import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | |||||
| import java.util.*; | import java.util.*; | ||||
| @TableName(value = "wx_refund_order") | @TableName(value = "wx_refund_order") | ||||
| @Data | @Data | ||||
| @EqualsAndHashCode(callSuper = true) | @EqualsAndHashCode(callSuper = true) | ||||
| @ToString | |||||
| public class WxRefundOrder extends TenantEntity { | public class WxRefundOrder extends TenantEntity { | ||||
| protected Long id; | protected Long id; | ||||
| @@ -15,7 +15,7 @@ public enum EnumMsgRecordType { | |||||
| INSIDE_ORDER_SUCCESS(100, "下订单成功"), | INSIDE_ORDER_SUCCESS(100, "下订单成功"), | ||||
| INSIDE_COUPON_VERIFY(101, "券核销"), | INSIDE_COUPON_VERIFY(101, "券核销"), | ||||
| INSIDE_C_LOGIN(102, "C端用户登录"), | INSIDE_C_LOGIN(102, "C端用户登录"), | ||||
| INSIDE_NOTIFY_PAY_SUCCESS(103, "微信支付回调"), | |||||
| //INSIDE_NOTIFY_PAY_SUCCESS(103, "微信支付回调"), | |||||
| INSIDE_NOTIFY_REFUND_SUCCESS(104, "微信退款回调"), | INSIDE_NOTIFY_REFUND_SUCCESS(104, "微信退款回调"), | ||||
| COUPON_STOCK(105, "券库存更新"), | COUPON_STOCK(105, "券库存更新"), | ||||
| ; | ; | ||||
| @@ -14,9 +14,9 @@ import com.iformall.domain.po.WxPayAccount; | |||||
| import com.iformall.domain.po.WxPayOrder; | import com.iformall.domain.po.WxPayOrder; | ||||
| import com.iformall.enums.EnumPayShare; | import com.iformall.enums.EnumPayShare; | ||||
| import com.iformall.enums.EnumPayWay; | import com.iformall.enums.EnumPayWay; | ||||
| import com.iformall.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.entity.PayExtraParam; | import com.iformall.service.pay.entity.PayExtraParam; | ||||
| import com.iformall.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | |||||
| public interface WxPayOrderService { | public interface WxPayOrderService { | ||||
| @@ -68,7 +68,7 @@ public interface WxPayOrderService { | |||||
| * @param payWay 支付方式 | * @param payWay 支付方式 | ||||
| * @return | * @return | ||||
| */ | */ | ||||
| String notify(Map<String, String> paramMap, EnumPayWay payWay); | |||||
| String shareNotify(Map<String, String> paramMap, EnumPayWay payWay); | |||||
| /** | /** | ||||
| * 支付成功处理 | * 支付成功处理 | ||||
| @@ -19,13 +19,14 @@ import com.iformall.pay.*; | |||||
| import com.iformall.service.*; | import com.iformall.service.*; | ||||
| import com.iformall.service.helper.WxPayOrderServiceHelper; | import com.iformall.service.helper.WxPayOrderServiceHelper; | ||||
| import com.iformall.service.pay.PayServiceFactory; | import com.iformall.service.pay.PayServiceFactory; | ||||
| import com.iformall.service.pay.entity.CreateCUser; | |||||
| import com.iformall.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.entity.PayExtraParam; | import com.iformall.service.pay.entity.PayExtraParam; | ||||
| import com.iformall.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.CDrivingPayService; | import com.iformall.service.pay.service.pay.CDrivingPayService; | ||||
| import com.iformall.service.pay.service.pay.CPassivePayService; | import com.iformall.service.pay.service.pay.CPassivePayService; | ||||
| import com.iformall.service.pay.service.pay.PayAdapterService; | import com.iformall.service.pay.service.pay.PayAdapterService; | ||||
| import com.iformall.service.pay.service.pay.entity.CreateCUser; | |||||
| import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.service.pay.service.share.entity.ShareNotifyAdapterResult; | |||||
| import com.iformall.utils.*; | import com.iformall.utils.*; | ||||
| import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
| @@ -877,119 +878,23 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { | |||||
| /** | /** | ||||
| * 提供微信支付回调调用 | |||||
| * 提供微信支付回调调用 --- 分账通知 | |||||
| * | * | ||||
| * @param paramMap 异步通知参数 | * @param paramMap 异步通知参数 | ||||
| * @param payWay 支付方式 | * @param payWay 支付方式 | ||||
| * @return | * @return | ||||
| */ | */ | ||||
| @Override | @Override | ||||
| public String notify(Map<String, String> paramMap, EnumPayWay payWay) { | |||||
| // how to get wechatAppId, wechatMchId, partnerKey | |||||
| String appId = paramMap.get("appid"); | |||||
| String subAppId = paramMap.get("sub_appid"); | |||||
| String mchId = paramMap.get("mch_id"); | |||||
| String subMchId = paramMap.get("sub_mch_id"); | |||||
| WxAppinfo appinfo = null; | |||||
| boolean isNormal = true; | |||||
| if (StringUtils.isBlank(subAppId) && StringUtils.isBlank(subMchId)) { | |||||
| // 普通商户号 | |||||
| appinfo = wxAppinfoMapper.findByAppId(appId); | |||||
| if (appinfo == null) { | |||||
| logger.error("appid not found: " + appId); | |||||
| throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND); | |||||
| } | |||||
| isNormal = true; | |||||
| } else { | |||||
| // 服务号 现在用hmac-sha256 | |||||
| appinfo = wxAppinfoMapper.findByAppId(subAppId); | |||||
| if (appinfo == null) { | |||||
| logger.error("subappid not found: " + subAppId); | |||||
| throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND); | |||||
| } | |||||
| isNormal = false; | |||||
| } | |||||
| WxPayAccount payAccount = wxPayAccountMapper.selectById(appinfo.getPayId()); | |||||
| if (payAccount == null) { | |||||
| throw new MallinkException(ErrorCode.MCH_INFO_NOT_FOUND); | |||||
| } | |||||
| String partnerKey = payAccount.getApiKey(); | |||||
| try { | |||||
| if (payWay == EnumPayWay.PAY_WAY_WECHAT) { | |||||
| boolean signVerified = false; | |||||
| if (isNormal) { | |||||
| // 普通商户号支付 | |||||
| signVerified = WxPayment.verifyNotify(paramMap, partnerKey); | |||||
| if (!signVerified) { | |||||
| logger.warn("notify order, wxpay checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR); | |||||
| } | |||||
| } else { | |||||
| // 服务号 现在用hmac-sha256 | |||||
| signVerified = WxPayment.verifyNotifyHMAC(paramMap, partnerKey); | |||||
| if (!signVerified) { | |||||
| logger.warn("notify order, wxpay checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR); | |||||
| } | |||||
| } | |||||
| if (!"SUCCESS".equals(paramMap.get("return_code"))) { | |||||
| logger.warn("notify order, wxpay status not success, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| SortedMap resultMap = new TreeMap(); | |||||
| resultMap.put("return_code", "FAIL"); | |||||
| resultMap.put("return_msg", "订单状态码非SUCCESS"); | |||||
| return XmlUtil.getRequestXml(resultMap); | |||||
| } | |||||
| String payOrderNo = paramMap.get("out_trade_no"); | |||||
| String timEndStr = paramMap.get("time_end"); | |||||
| Long payOrderId = Long.valueOf(payOrderNo); | |||||
| WxPayOrder payOrder = wxPayOrderMapper.selectById(payOrderId); | |||||
| if (payOrder == null) { | |||||
| logger.warn("notify order, wxpay check pay order not exists, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| SortedMap resultMap = new TreeMap(); | |||||
| resultMap.put("return_code", "FAIL"); | |||||
| resultMap.put("return_msg", "订单不存在"); | |||||
| return XmlUtil.getRequestXml(resultMap); | |||||
| } | |||||
| // 验证支付金额 | |||||
| if (!paramMap.get("total_fee").equals(payOrder.getPayAmount().toString())) { | |||||
| logger.warn("notify order, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| SortedMap resultMap = new TreeMap(); | |||||
| resultMap.put("return_code", "FAIL"); | |||||
| resultMap.put("return_msg", "订单总金额不一致"); | |||||
| return XmlUtil.getRequestXml(resultMap); | |||||
| } | |||||
| Date timeEnd = null; | |||||
| try { | |||||
| timeEnd = Utility.getDateFromString(timEndStr); | |||||
| } catch (ParseException e) { | |||||
| logger.error("解析timeEnd失败"); | |||||
| timeEnd = new Date(); | |||||
| } | |||||
| payOrder.setPayTimeEnd(timeEnd); | |||||
| payOrder.setPayEndFrom(EnumPayEndFrom.CALLBACK.getCode()); | |||||
| // 处理支付成功 | |||||
| handleOrderPaySuccess(payOrder, paramMap.get("transaction_id")); | |||||
| logger.info("notify order, wxpay checksign success, paramMap:{}, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| SortedMap resultMap = new TreeMap(); | |||||
| resultMap.put("return_code", "SUCCESS"); | |||||
| resultMap.put("return_msg", "OK"); | |||||
| return XmlUtil.getRequestXml(resultMap); | |||||
| } | |||||
| } catch (RuntimeException e) { | |||||
| logger.warn("notify order, checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR); | |||||
| } | |||||
| SortedMap resultMap = new TreeMap(); | |||||
| resultMap.put("return_code", "FAIL"); | |||||
| resultMap.put("return_msg", "FAILED"); | |||||
| return XmlUtil.getRequestXml(resultMap); | |||||
| public String shareNotify(Map<String, String> paramMap, EnumPayWay payWay) { | |||||
| ShareNotifyAdapterResult shareResult = payServiceFactory.getPayShareAdapterService(payWay.getCode()).notify(paramMap,payWay); | |||||
| if (shareResult.isSuccess()) { | |||||
| // 处理支付成功 | |||||
| shareResult.getPayOrder().setPayEndFrom(EnumPayEndFrom.CALLBACK.getCode()); | |||||
| handleOrderPaySuccess(shareResult.getPayOrder(), shareResult.getTranscationId()); | |||||
| return shareResult.getReturnJson(); | |||||
| }else { | |||||
| return shareResult.getReturnJson(); | |||||
| } | |||||
| } | } | ||||
| @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | ||||
| @@ -21,7 +21,7 @@ import com.iformall.mapper.*; | |||||
| import com.iformall.pay.*; | import com.iformall.pay.*; | ||||
| import com.iformall.service.WxProfitSharingOrderService; | import com.iformall.service.WxProfitSharingOrderService; | ||||
| import com.iformall.service.pay.PayServiceFactory; | import com.iformall.service.pay.PayServiceFactory; | ||||
| import com.iformall.service.pay.entity.PayShareResult; | |||||
| import com.iformall.service.pay.service.share.entity.PayShareResult; | |||||
| import com.iformall.utils.BeanUtils; | import com.iformall.utils.BeanUtils; | ||||
| import com.iformall.utils.DateUtils; | import com.iformall.utils.DateUtils; | ||||
| import com.iformall.utils.Utility; | import com.iformall.utils.Utility; | ||||
| @@ -18,17 +18,17 @@ import java.util.Map; | |||||
| * @author Stormeye Wu | * @author Stormeye Wu | ||||
| * @date 2019/5/10 | * @date 2019/5/10 | ||||
| */ | */ | ||||
| @Service | |||||
| public class FmInsideNotifyPaySuccessMsgServiceImpl implements MsgSendService { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private WxPayOrderService wxPayOrderService; | |||||
| @Override | |||||
| public void send(BaseMsg baseMsg) throws Exception { | |||||
| FmInsideNotifyPaySuccessMsg msg = (FmInsideNotifyPaySuccessMsg)baseMsg; | |||||
| Map<String, String> paramMap = JSON.parseObject(msg.getJsonMsg(), Map.class); | |||||
| wxPayOrderService.notify(paramMap, EnumPayWay.getEnum(msg.getPayWay())); | |||||
| } | |||||
| } | |||||
| //@Service | |||||
| //public class FmInsideNotifyPaySuccessMsgServiceImpl implements MsgSendService { | |||||
| // private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| // | |||||
| // @Autowired | |||||
| // private WxPayOrderService wxPayOrderService; | |||||
| // | |||||
| // @Override | |||||
| // public void send(BaseMsg baseMsg) throws Exception { | |||||
| // FmInsideNotifyPaySuccessMsg msg = (FmInsideNotifyPaySuccessMsg)baseMsg; | |||||
| // Map<String, String> paramMap = JSON.parseObject(msg.getJsonMsg(), Map.class); | |||||
| // wxPayOrderService.notify(paramMap, EnumPayWay.getEnum(msg.getPayWay())); | |||||
| // } | |||||
| //} | |||||
| @@ -14,8 +14,11 @@ import com.iformall.service.WxPayOrderService; | |||||
| import com.iformall.service.pay.service.pay.CDrivingPayService; | import com.iformall.service.pay.service.pay.CDrivingPayService; | ||||
| import com.iformall.service.pay.service.pay.CPassivePayService; | import com.iformall.service.pay.service.pay.CPassivePayService; | ||||
| import com.iformall.service.pay.service.pay.PayAdapterService; | import com.iformall.service.pay.service.pay.PayAdapterService; | ||||
| import com.iformall.service.pay.service.pay.miniApp.wx.appPay.WxMiniAppPayAdapterService; | |||||
| import com.iformall.service.pay.service.pay.miniApp.wx.maPay.WxMiniMaPayAdapterService; | |||||
| import com.iformall.service.pay.service.pay.wx.h5.WxH5PayService; | |||||
| import com.iformall.service.pay.service.pay.wx.miniApp.appPay.WxMiniAppPayAdapterService; | |||||
| import com.iformall.service.pay.service.pay.wx.miniApp.maPay.WxMiniMaPayAdapterService; | |||||
| import com.iformall.service.pay.service.refund.RefundPayAdapterService; | |||||
| import com.iformall.service.pay.service.refund.wx.WxRefundAdapterService; | |||||
| import com.iformall.service.pay.service.share.PayShareAdapterService; | import com.iformall.service.pay.service.share.PayShareAdapterService; | ||||
| import com.iformall.service.pay.service.share.neupos.NeuPosPayShareService; | import com.iformall.service.pay.service.share.neupos.NeuPosPayShareService; | ||||
| import com.iformall.service.pay.service.share.wx.WxPayShareService; | import com.iformall.service.pay.service.share.wx.WxPayShareService; | ||||
| @@ -29,22 +32,60 @@ public class PayServiceFactory { | |||||
| private Map<Integer,PayAdapterService> serviceMap = null; | private Map<Integer,PayAdapterService> serviceMap = null; | ||||
| private Map<Integer,PayShareAdapterService> shareMap = null; | private Map<Integer,PayShareAdapterService> shareMap = null; | ||||
| private Map<Integer,RefundPayAdapterService> refundMap = null; | |||||
| @Autowired | @Autowired | ||||
| WxMiniAppPayAdapterService wxMiniAppPayService; | WxMiniAppPayAdapterService wxMiniAppPayService; | ||||
| @Autowired | @Autowired | ||||
| WxMiniMaPayAdapterService wxMiniAppMaPayService; | WxMiniMaPayAdapterService wxMiniAppMaPayService; | ||||
| @Autowired | @Autowired | ||||
| WxPayOrderService wxPayOrderService; | |||||
| WxH5PayService wxH5PayService; | |||||
| @Autowired | @Autowired | ||||
| WxPayShareService wxShareService; | WxPayShareService wxShareService; | ||||
| @Autowired | @Autowired | ||||
| NeuPosPayShareService neuPosPayShareService; | NeuPosPayShareService neuPosPayShareService; | ||||
| @Autowired | |||||
| WxRefundAdapterService wxRefundService; | |||||
| private Map<Integer,PayAdapterService> getServiceMap() { | |||||
| if (null == serviceMap) { | |||||
| serviceMap = new ConcurrentHashMap<Integer,PayAdapterService>(); | |||||
| serviceMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode(), wxMiniAppPayService); | |||||
| serviceMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode(), wxMiniAppMaPayService); | |||||
| serviceMap.put(EnumPayWay.PAY_WAY_WECHAT_WAP.getCode(), wxH5PayService); | |||||
| } | |||||
| return serviceMap; | |||||
| } | |||||
| private Map<Integer,PayShareAdapterService> getShareMap(){ | |||||
| if (null == shareMap ) { | |||||
| shareMap = new ConcurrentHashMap<Integer, PayShareAdapterService>(); | |||||
| shareMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode(), wxShareService); | |||||
| shareMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode(), wxShareService); | |||||
| shareMap.put(EnumPayWay.PAY_WAY_POS_NEU.getCode(), neuPosPayShareService); | |||||
| } | |||||
| return shareMap; | |||||
| } | |||||
| private Map<Integer,RefundPayAdapterService> getRefundMap(){ | |||||
| if (null == refundMap ) { | |||||
| refundMap = new ConcurrentHashMap<Integer, RefundPayAdapterService>(); | |||||
| refundMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode(), wxRefundService); | |||||
| refundMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode(), wxRefundService); | |||||
| } | |||||
| return refundMap; | |||||
| } | |||||
| public PayAdapterService getPayAdapterService(Integer type) throws MallinkException{ | public PayAdapterService getPayAdapterService(Integer type) throws MallinkException{ | ||||
| PayAdapterService service = getServiceMap().get(type); | PayAdapterService service = getServiceMap().get(type); | ||||
| if (null == service) { | if (null == service) { | ||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payType["+type+"] 支付service未找到"); | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 支付service未找到"); | |||||
| } | } | ||||
| return service; | return service; | ||||
| } | } | ||||
| @@ -52,51 +93,40 @@ public class PayServiceFactory { | |||||
| public CDrivingPayService getCDrivingPayService(Integer type) throws MallinkException{ | public CDrivingPayService getCDrivingPayService(Integer type) throws MallinkException{ | ||||
| PayAdapterService service = getServiceMap().get(type); | PayAdapterService service = getServiceMap().get(type); | ||||
| if (null == service) { | if (null == service) { | ||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payType["+type+"] 支付service未找到"); | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 支付service未找到"); | |||||
| } | } | ||||
| if (service instanceof CDrivingPayService) { | if (service instanceof CDrivingPayService) { | ||||
| return (CDrivingPayService) service; | return (CDrivingPayService) service; | ||||
| }else { | }else { | ||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payType["+type+"] 支付service不是CDrivingPayService"); | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 支付service不是CDrivingPayService"); | |||||
| } | } | ||||
| } | } | ||||
| public CPassivePayService getCPassivePayService(Integer type) throws MallinkException{ | public CPassivePayService getCPassivePayService(Integer type) throws MallinkException{ | ||||
| PayAdapterService service = getServiceMap().get(type); | PayAdapterService service = getServiceMap().get(type); | ||||
| if (null == service) { | if (null == service) { | ||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payType["+type+"] 支付service未找到"); | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 支付service未找到"); | |||||
| } | } | ||||
| if (service instanceof CPassivePayService) { | if (service instanceof CPassivePayService) { | ||||
| return (CPassivePayService) service; | return (CPassivePayService) service; | ||||
| }else { | }else { | ||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payType["+type+"] 支付service不是CPassivePayService"); | |||||
| } | |||||
| } | |||||
| private Map<Integer,PayAdapterService> getServiceMap() { | |||||
| if (null != serviceMap) { | |||||
| serviceMap = new ConcurrentHashMap<Integer,PayAdapterService>(); | |||||
| serviceMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode(), wxMiniAppPayService); | |||||
| serviceMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode(), wxMiniAppMaPayService); | |||||
| } | |||||
| return serviceMap; | |||||
| } | |||||
| private Map<Integer,PayShareAdapterService> getShareMap(){ | |||||
| if (null != shareMap ) { | |||||
| shareMap = new ConcurrentHashMap<Integer, PayShareAdapterService>(); | |||||
| shareMap.put(EnumPayWay.PAY_WAY_WECHAT.getCode(), wxShareService); | |||||
| shareMap.put(EnumPayWay.PAY_WAY_WECHAT_MA.getCode(), wxShareService); | |||||
| shareMap.put(EnumPayWay.PAY_WAY_POS_NEU.getCode(), neuPosPayShareService); | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 支付service不是CPassivePayService"); | |||||
| } | } | ||||
| return shareMap; | |||||
| } | } | ||||
| public PayShareAdapterService getPayShareAdapterService(Integer type) throws MallinkException{ | public PayShareAdapterService getPayShareAdapterService(Integer type) throws MallinkException{ | ||||
| PayShareAdapterService shareService = getShareMap().get(type); | PayShareAdapterService shareService = getShareMap().get(type); | ||||
| if (null == shareService) { | if (null == shareService) { | ||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payType["+type+"] 分账service未找到"); | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 分账service未找到"); | |||||
| } | } | ||||
| return shareService; | return shareService; | ||||
| } | } | ||||
| public RefundPayAdapterService getRefundPayAdapterService(Integer type) throws MallinkException{ | |||||
| RefundPayAdapterService refundService = getRefundMap().get(type); | |||||
| if (null == refundService) { | |||||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"payWay["+type+"] 退款service未找到"); | |||||
| } | |||||
| return refundService; | |||||
| } | |||||
| } | } | ||||
| @@ -7,9 +7,9 @@ import com.iformall.domain.po.WxOrder; | |||||
| import com.iformall.domain.po.WxPayAccount; | import com.iformall.domain.po.WxPayAccount; | ||||
| import com.iformall.domain.po.WxPayOrder; | import com.iformall.domain.po.WxPayOrder; | ||||
| import com.iformall.enums.EnumPayShare; | import com.iformall.enums.EnumPayShare; | ||||
| import com.iformall.service.pay.entity.CreateCUser; | |||||
| import com.iformall.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.entity.PayExtraParam; | import com.iformall.service.pay.entity.PayExtraParam; | ||||
| import com.iformall.service.pay.service.pay.entity.CreateCUser; | |||||
| import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | |||||
| /** | /** | ||||
| * C端被动发起的支付 | * C端被动发起的支付 | ||||
| @@ -6,9 +6,9 @@ import com.iformall.domain.po.WxOrder; | |||||
| import com.iformall.domain.po.WxPayAccount; | import com.iformall.domain.po.WxPayAccount; | ||||
| import com.iformall.domain.po.WxPayOrder; | import com.iformall.domain.po.WxPayOrder; | ||||
| import com.iformall.enums.EnumPayShare; | import com.iformall.enums.EnumPayShare; | ||||
| import com.iformall.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.entity.PayExtraParam; | import com.iformall.service.pay.entity.PayExtraParam; | ||||
| import com.iformall.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | |||||
| public interface PayAdapterService { | public interface PayAdapterService { | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.iformall.service.pay.entity; | |||||
| package com.iformall.service.pay.service.pay.entity; | |||||
| import java.io.Serializable; | import java.io.Serializable; | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.iformall.service.pay.entity; | |||||
| package com.iformall.service.pay.service.pay.entity; | |||||
| import java.io.Serializable; | import java.io.Serializable; | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.iformall.service.pay.entity; | |||||
| package com.iformall.service.pay.service.pay.entity; | |||||
| import java.io.Serializable; | import java.io.Serializable; | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.iformall.service.pay.service.pay.miniApp.wx; | |||||
| package com.iformall.service.pay.service.pay.wx; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| @@ -7,8 +7,8 @@ import com.iformall.domain.po.WxOrder; | |||||
| import com.iformall.domain.po.WxPayAccount; | import com.iformall.domain.po.WxPayAccount; | ||||
| import com.iformall.domain.po.WxPayOrder; | import com.iformall.domain.po.WxPayOrder; | ||||
| import com.iformall.service.helper.WxPayOrderServiceHelper; | import com.iformall.service.helper.WxPayOrderServiceHelper; | ||||
| import com.iformall.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.PayAdapterService; | import com.iformall.service.pay.service.pay.PayAdapterService; | ||||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | |||||
| public class BaseWxPayAdapterService { | public class BaseWxPayAdapterService { | ||||
| @@ -0,0 +1,45 @@ | |||||
| package com.iformall.service.pay.service.pay.wx.h5; | |||||
| import java.util.Date; | |||||
| import org.springframework.stereotype.Service; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.domain.po.WxOrder; | |||||
| import com.iformall.domain.po.WxPayAccount; | |||||
| import com.iformall.domain.po.WxPayOrder; | |||||
| import com.iformall.enums.EnumPayShare; | |||||
| import com.iformall.service.pay.entity.PayExtraParam; | |||||
| import com.iformall.service.pay.service.pay.CDrivingPayService; | |||||
| import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.wx.BaseWxPayAdapterService; | |||||
| @Service | |||||
| public class WxH5PayService extends BaseWxPayAdapterService implements CDrivingPayService{ | |||||
| @Override | |||||
| public PayAdapterResult pay(WxPayAccount payAccount, WxOrder order, WxPayOrder record, EnumPayShare isShare, | |||||
| WxAppinfo appInfo, Date currentDate, PayExtraParam params) throws Exception { | |||||
| // TODO Auto-generated method stub | |||||
| return null; | |||||
| } | |||||
| @Override | |||||
| public PayQueryAdapterResult queryPayStatus(WxPayOrder oldRecord, WxOrder order, WxAppinfo appInfo, | |||||
| WxPayAccount payAccount) throws Exception { | |||||
| return super.queryPayStatus(oldRecord, order, appInfo, payAccount); | |||||
| } | |||||
| @Override | |||||
| public int queryPayStatus(PayQueryAdapterResult statusObject, String orderOutNo) throws Exception { | |||||
| return super.queryPayStatus(statusObject, orderOutNo); | |||||
| } | |||||
| @Override | |||||
| public int queryPayStatusCode(WxPayOrder oldRecord, WxOrder order, WxAppinfo appInfo, WxPayAccount payAccount) | |||||
| throws Exception { | |||||
| return super.queryPayStatusCode(oldRecord, order, appInfo, payAccount); | |||||
| } | |||||
| } | |||||
| @@ -1,4 +1,4 @@ | |||||
| package com.iformall.service.pay.service.pay.miniApp.wx.appPay; | |||||
| package com.iformall.service.pay.service.pay.wx.miniApp.appPay; | |||||
| import java.util.Date; | import java.util.Date; | ||||
| import java.util.Map; | import java.util.Map; | ||||
| @@ -22,11 +22,11 @@ import com.iformall.pay.WxPay; | |||||
| import com.iformall.pay.WxPayOrderP; | import com.iformall.pay.WxPayOrderP; | ||||
| import com.iformall.pay.WxPayOrderSP; | import com.iformall.pay.WxPayOrderSP; | ||||
| import com.iformall.pay.WxPayment; | import com.iformall.pay.WxPayment; | ||||
| import com.iformall.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.entity.PayExtraParam; | import com.iformall.service.pay.entity.PayExtraParam; | ||||
| import com.iformall.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.CDrivingPayService; | import com.iformall.service.pay.service.pay.CDrivingPayService; | ||||
| import com.iformall.service.pay.service.pay.miniApp.wx.BaseWxPayAdapterService; | |||||
| import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.wx.BaseWxPayAdapterService; | |||||
| import com.iformall.utils.BeanUtils; | import com.iformall.utils.BeanUtils; | ||||
| import com.iformall.utils.MapUtil; | import com.iformall.utils.MapUtil; | ||||
| import com.iformall.utils.Utility; | import com.iformall.utils.Utility; | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.iformall.service.pay.service.pay.miniApp.wx.maPay; | |||||
| package com.iformall.service.pay.service.pay.wx.miniApp.maPay; | |||||
| import java.util.Date; | import java.util.Date; | ||||
| import java.util.Map; | import java.util.Map; | ||||
| @@ -22,12 +22,12 @@ import com.iformall.pay.WxMicroPayOrderSP; | |||||
| import com.iformall.pay.WxPay; | import com.iformall.pay.WxPay; | ||||
| import com.iformall.pay.WxPayment; | import com.iformall.pay.WxPayment; | ||||
| import com.iformall.service.WxCUserService; | import com.iformall.service.WxCUserService; | ||||
| import com.iformall.service.pay.entity.CreateCUser; | |||||
| import com.iformall.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.entity.PayExtraParam; | import com.iformall.service.pay.entity.PayExtraParam; | ||||
| import com.iformall.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.CPassivePayService; | import com.iformall.service.pay.service.pay.CPassivePayService; | ||||
| import com.iformall.service.pay.service.pay.miniApp.wx.BaseWxPayAdapterService; | |||||
| import com.iformall.service.pay.service.pay.entity.CreateCUser; | |||||
| import com.iformall.service.pay.service.pay.entity.PayAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.entity.PayQueryAdapterResult; | |||||
| import com.iformall.service.pay.service.pay.wx.BaseWxPayAdapterService; | |||||
| import com.iformall.utils.BeanUtils; | import com.iformall.utils.BeanUtils; | ||||
| import com.iformall.utils.Utility; | import com.iformall.utils.Utility; | ||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
| @@ -0,0 +1,42 @@ | |||||
| package com.iformall.service.pay.service.refund; | |||||
| import java.util.Map; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.domain.po.WxPayAccount; | |||||
| import com.iformall.domain.po.WxPayOrder; | |||||
| import com.iformall.domain.po.WxRefundOrder; | |||||
| import com.iformall.enums.EnumPayType; | |||||
| import com.iformall.enums.EnumPayWay; | |||||
| import com.iformall.service.pay.service.refund.entity.RefundAdapterResult; | |||||
| import com.iformall.service.pay.service.refund.entity.RefundNotifyAdapterResult; | |||||
| public interface RefundPayAdapterService { | |||||
| /** | |||||
| * API退款 | |||||
| * @param payAccount | |||||
| * @param appInfo | |||||
| * @param record | |||||
| * @param payOrder | |||||
| * @param payType | |||||
| * @return | |||||
| */ | |||||
| public RefundAdapterResult refund(WxPayAccount payAccount,WxAppinfo appInfo,WxRefundOrder record,WxPayOrder payOrder,EnumPayType payType); | |||||
| /** | |||||
| * API查询退款 | |||||
| * @param appInfo | |||||
| * @param payAccount | |||||
| * @param record | |||||
| * @return | |||||
| */ | |||||
| public RefundAdapterResult queryRefund(WxAppinfo appInfo,WxPayAccount payAccount, WxRefundOrder record); | |||||
| /** | |||||
| * 平台方 异步通知 | |||||
| * @param paramMap | |||||
| * @param payWay | |||||
| */ | |||||
| public RefundNotifyAdapterResult notify(Map<String, String> paramMap, EnumPayWay payWay); | |||||
| } | |||||
| @@ -0,0 +1,50 @@ | |||||
| package com.iformall.service.pay.service.refund.entity; | |||||
| import java.io.Serializable; | |||||
| public class RefundAdapterResult implements Serializable{ | |||||
| private static final long serialVersionUID = -6647306162758854293L; | |||||
| private boolean isSuccess; | |||||
| private Integer code; | |||||
| private String msg; | |||||
| private Object data; | |||||
| public RefundAdapterResult() { | |||||
| } | |||||
| public RefundAdapterResult(boolean isSuccess,Integer code,String msg,Object data) { | |||||
| this.isSuccess = isSuccess; | |||||
| this.msg = msg; | |||||
| this.data = data; | |||||
| } | |||||
| public boolean isSuccess() { | |||||
| return isSuccess; | |||||
| } | |||||
| public void setSuccess(boolean isSuccess) { | |||||
| this.isSuccess = isSuccess; | |||||
| } | |||||
| public String getMsg() { | |||||
| return msg; | |||||
| } | |||||
| public void setMsg(String msg) { | |||||
| this.msg = msg; | |||||
| } | |||||
| public Object getData() { | |||||
| return data; | |||||
| } | |||||
| public void setData(Object data) { | |||||
| this.data = data; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public void setCode(Integer code) { | |||||
| this.code = code; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,87 @@ | |||||
| package com.iformall.service.pay.service.refund.entity; | |||||
| import java.io.Serializable; | |||||
| import com.iformall.domain.po.WxRefundOrder; | |||||
| public class RefundNotifyAdapterResult implements Serializable{ | |||||
| private static final long serialVersionUID = -6647306162758854293L; | |||||
| private boolean isSuccess; | |||||
| private Integer code; | |||||
| private String msg; | |||||
| private String returnJson; | |||||
| private String transcationId; | |||||
| private String refundId; | |||||
| private WxRefundOrder refundOrder; | |||||
| public RefundNotifyAdapterResult() { | |||||
| } | |||||
| public RefundNotifyAdapterResult(boolean isSuccess,Integer code,String msg,String returnJson) { | |||||
| this.isSuccess = isSuccess; | |||||
| this.msg = msg; | |||||
| this.returnJson = returnJson; | |||||
| } | |||||
| public RefundNotifyAdapterResult(String transcationId,String refundId,WxRefundOrder refundOrder,String returnJson) { | |||||
| this.isSuccess = true; | |||||
| this.transcationId = transcationId; | |||||
| this.refundId = refundId; | |||||
| this.refundOrder = refundOrder; | |||||
| this.returnJson = returnJson; | |||||
| } | |||||
| public boolean isSuccess() { | |||||
| return isSuccess; | |||||
| } | |||||
| public void setSuccess(boolean isSuccess) { | |||||
| this.isSuccess = isSuccess; | |||||
| } | |||||
| public String getMsg() { | |||||
| return msg; | |||||
| } | |||||
| public void setMsg(String msg) { | |||||
| this.msg = msg; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public void setCode(Integer code) { | |||||
| this.code = code; | |||||
| } | |||||
| public String getTranscationId() { | |||||
| return transcationId; | |||||
| } | |||||
| public void setTranscationId(String transcationId) { | |||||
| this.transcationId = transcationId; | |||||
| } | |||||
| public String getRefundId() { | |||||
| return refundId; | |||||
| } | |||||
| public void setRefundId(String refundId) { | |||||
| this.refundId = refundId; | |||||
| } | |||||
| public String getReturnJson() { | |||||
| return returnJson; | |||||
| } | |||||
| public void setReturnJson(String returnJson) { | |||||
| this.returnJson = returnJson; | |||||
| } | |||||
| public WxRefundOrder getRefundOrder() { | |||||
| return refundOrder; | |||||
| } | |||||
| public void setRefundOrder(WxRefundOrder refundOrder) { | |||||
| this.refundOrder = refundOrder; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,636 @@ | |||||
| package com.iformall.service.pay.service.refund.wx; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| import java.util.SortedMap; | |||||
| import java.util.TreeMap; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| import com.alibaba.fastjson.JSON; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.common.Result; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.domain.po.WxPayAccount; | |||||
| import com.iformall.domain.po.WxPayOrder; | |||||
| import com.iformall.domain.po.WxRefundOrder; | |||||
| import com.iformall.enums.EnumPayMode; | |||||
| import com.iformall.enums.EnumPayType; | |||||
| import com.iformall.enums.EnumPayWay; | |||||
| import com.iformall.enums.EnumRefundStatus; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.mapper.WxAppinfoMapper; | |||||
| import com.iformall.mapper.WxPayAccountMapper; | |||||
| import com.iformall.mapper.WxPayOrderMapper; | |||||
| import com.iformall.mapper.WxRefundOrderMapper; | |||||
| import com.iformall.pay.WxPay; | |||||
| import com.iformall.pay.WxPayment; | |||||
| import com.iformall.pay.WxRefundOrderP; | |||||
| import com.iformall.pay.WxRefundOrderSP; | |||||
| import com.iformall.service.pay.service.refund.RefundPayAdapterService; | |||||
| import com.iformall.service.pay.service.refund.entity.RefundAdapterResult; | |||||
| import com.iformall.service.pay.service.refund.entity.RefundNotifyAdapterResult; | |||||
| import com.iformall.utils.BeanUtils; | |||||
| import com.iformall.utils.CipherUtil; | |||||
| import com.iformall.utils.Utility; | |||||
| import com.iformall.utils.XmlUtil; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| @Slf4j | |||||
| @Service | |||||
| public class WxRefundAdapterService implements RefundPayAdapterService{ | |||||
| JSONObject errorRefundReqMap = JSON.parseObject("{\n" + | |||||
| " \"SYSTEMERROR\": {\n" + | |||||
| " \"detail\": \"接口返回错误\",\n" + | |||||
| " \"reason\": \"系统超时等\",\n" + | |||||
| " \"resolution\": \"请不要更换商户退款单号,请使用相同参数再次调用API。\"\n" + | |||||
| " },\n" + | |||||
| " \"BIZERR_NEED_RETRY\": {\n" + | |||||
| " \"detail\": \"退款业务流程错误,需要商户触发重试来解决\",\n" + | |||||
| " \"reason\": \"并发情况下,业务被拒绝,商户重试即可解决\",\n" + | |||||
| " \"resolution\": \"请不要更换商户退款单号,请使用相同参数再次调用API。\"\n" + | |||||
| " },\n" + | |||||
| " \"TRADE_OVERDUE\": {\n" + | |||||
| " \"detail\": \"订单已经超过退款期限\",\n" + | |||||
| " \"reason\": \"订单已经超过可退款的最大期限(支付后一年内可退款)\\t\",\n" + | |||||
| " \"resolution\": \"请选择其他方式自行退款\"\n" + | |||||
| " },\n" + | |||||
| " \"ERROR\": {\n" + | |||||
| " \"detail\": \"业务错误\",\n" + | |||||
| " \"reason\": \"申请退款业务发生错误\",\n" + | |||||
| " \"resolution\": \"该错误都会返回具体的错误原因,请根据实际返回做相应处理。\"\n" + | |||||
| " },\n" + | |||||
| " \"USER_ACCOUNT_ABNORMAL\": {\n" + | |||||
| " \"detail\": \"退款请求失败\",\n" + | |||||
| " \"reason\": \"用户帐号注销\",\n" + | |||||
| " \"resolution\": \"此状态代表退款申请失败,商户可自行处理退款。\"\n" + | |||||
| " },\n" + | |||||
| " \"INVALID_REQ_TOO_MUCH\": {\n" + | |||||
| " \"detail\": \"无效请求过多\",\n" + | |||||
| " \"reason\": \"连续错误请求数过多被系统短暂屏蔽\\t\",\n" + | |||||
| " \"resolution\": \"请检查业务是否正常,确认业务正常后请在1分钟后再来重试\"\n" + | |||||
| " },\n" + | |||||
| " \"NOTENOUGH\": {\n" + | |||||
| " \"detail\": \"余额不足\",\n" + | |||||
| " \"reason\": \"商户可用退款余额不足\",\n" + | |||||
| " \"resolution\": \"此状态代表退款申请失败,商户可根据具体的错误提示做相应的处理。\"\n" + | |||||
| " },\n" + | |||||
| " \"INVALID_TRANSACTIONID\": {\n" + | |||||
| " \"detail\": \"无效transaction_id\",\n" + | |||||
| " \"reason\": \"请求参数未按指引进行填写\",\n" + | |||||
| " \"resolution\": \"请求参数错误,检查原交易号是否存在或发起支付交易接口返回失败\"\n" + | |||||
| " },\n" + | |||||
| " \"PARAM_ERROR\": {\n" + | |||||
| " \"detail\": \"参数错误\",\n" + | |||||
| " \"reason\": \"请求参数未按指引进行填写\",\n" + | |||||
| " \"resolution\": \"请求参数错误,请重新检查再调用退款申请\"\n" + | |||||
| " },\n" + | |||||
| " \"APPID_NOT_EXIST\": {\n" + | |||||
| " \"detail\": \"APPID不存在\",\n" + | |||||
| " \"reason\": \"参数中缺少APPID\",\n" + | |||||
| " \"resolution\": \"请检查APPID是否正确\"\n" + | |||||
| " },\n" + | |||||
| " \"MCHID_NOT_EXIST\": {\n" + | |||||
| " \"detail\": \"MCHID不存在\",\n" + | |||||
| " \"reason\": \"参数中缺少MCHID\",\n" + | |||||
| " \"resolution\": \"请检查MCHID是否正确\"\n" + | |||||
| " },\n" + | |||||
| " \"REQUIRE_POST_METHOD\": {\n" + | |||||
| " \"detail\": \"请使用post方法\",\n" + | |||||
| " \"reason\": \"未使用post传递参数\",\n" + | |||||
| " \"resolution\": \"请检查请求参数是否通过post方法提交\"\n" + | |||||
| " },\n" + | |||||
| " \"SIGNERROR\": {\n" + | |||||
| " \"detail\": \"签名错误\",\n" + | |||||
| " \"reason\": \"参数签名结果不正确\",\n" + | |||||
| " \"resolution\": \"请检查签名参数和方法是否都符合签名算法要求\"\n" + | |||||
| " },\n" + | |||||
| " \"XML_FORMAT_ERROR\": {\n" + | |||||
| " \"detail\": \"XML格式错误\",\n" + | |||||
| " \"reason\": \"XML格式错误\",\n" + | |||||
| " \"resolution\": \"请检查XML参数格式是否正确\"\n" + | |||||
| " },\n" + | |||||
| " \"FREQUENCY_LIMITED\": {\n" + | |||||
| " \"detail\": \"频率限制\",\n" + | |||||
| " \"reason\": \"2个月之前的订单申请退款有频率限制\",\n" + | |||||
| " \"resolution\": \"该笔退款未受理,请降低频率后重试\"\n" + | |||||
| " }\n" + | |||||
| "}"); | |||||
| JSONObject errorRefundQueryMap = JSON.parseObject("{\n" + | |||||
| " \"SYSTEMERROR\": {\n" + | |||||
| " \"detail\": \"接口返回错误\",\n" + | |||||
| " \"reason\": \"系统超时等\",\n" + | |||||
| " \"resolution\": \"请不要更换商户退款单号,请使用相同参数再次调用API。\"\n" + | |||||
| " },\n" + | |||||
| " \"BIZERR_NEED_RETRY\": {\n" + | |||||
| " \"detail\": \"退款业务流程错误,需要商户触发重试来解决\",\n" + | |||||
| " \"reason\": \"并发情况下,业务被拒绝,商户重试即可解决\",\n" + | |||||
| " \"resolution\": \"请不要更换商户退款单号,请使用相同参数再次调用API。\"\n" + | |||||
| " },\n" + | |||||
| " \"TRADE_OVERDUE\": {\n" + | |||||
| " \"detail\": \"订单已经超过退款期限\",\n" + | |||||
| " \"reason\": \"订单已经超过可退款的最大期限(支付后一年内可退款)\\t\",\n" + | |||||
| " \"resolution\": \"请选择其他方式自行退款\"\n" + | |||||
| " },\n" + | |||||
| " \"ERROR\": {\n" + | |||||
| " \"detail\": \"业务错误\",\n" + | |||||
| " \"reason\": \"申请退款业务发生错误\",\n" + | |||||
| " \"resolution\": \"该错误都会返回具体的错误原因,请根据实际返回做相应处理。\"\n" + | |||||
| " },\n" + | |||||
| " \"USER_ACCOUNT_ABNORMAL\": {\n" + | |||||
| " \"detail\": \"退款请求失败\",\n" + | |||||
| " \"reason\": \"用户帐号注销\",\n" + | |||||
| " \"resolution\": \"此状态代表退款申请失败,商户可自行处理退款。\"\n" + | |||||
| " },\n" + | |||||
| " \"INVALID_REQ_TOO_MUCH\": {\n" + | |||||
| " \"detail\": \"无效请求过多\",\n" + | |||||
| " \"reason\": \"连续错误请求数过多被系统短暂屏蔽\\t\",\n" + | |||||
| " \"resolution\": \"请检查业务是否正常,确认业务正常后请在1分钟后再来重试\"\n" + | |||||
| " },\n" + | |||||
| " \"NOTENOUGH\": {\n" + | |||||
| " \"detail\": \"余额不足\",\n" + | |||||
| " \"reason\": \"商户可用退款余额不足\",\n" + | |||||
| " \"resolution\": \"此状态代表退款申请失败,商户可根据具体的错误提示做相应的处理。\"\n" + | |||||
| " },\n" + | |||||
| " \"INVALID_TRANSACTIONID\": {\n" + | |||||
| " \"detail\": \"无效transaction_id\",\n" + | |||||
| " \"reason\": \"请求参数未按指引进行填写\",\n" + | |||||
| " \"resolution\": \"请求参数错误,检查原交易号是否存在或发起支付交易接口返回失败\"\n" + | |||||
| " },\n" + | |||||
| " \"PARAM_ERROR\": {\n" + | |||||
| " \"detail\": \"参数错误\",\n" + | |||||
| " \"reason\": \"请求参数未按指引进行填写\",\n" + | |||||
| " \"resolution\": \"请求参数错误,请重新检查再调用退款申请\"\n" + | |||||
| " },\n" + | |||||
| " \"APPID_NOT_EXIST\": {\n" + | |||||
| " \"detail\": \"APPID不存在\",\n" + | |||||
| " \"reason\": \"参数中缺少APPID\",\n" + | |||||
| " \"resolution\": \"请检查APPID是否正确\"\n" + | |||||
| " },\n" + | |||||
| " \"MCHID_NOT_EXIST\": {\n" + | |||||
| " \"detail\": \"MCHID不存在\",\n" + | |||||
| " \"reason\": \"参数中缺少MCHID\",\n" + | |||||
| " \"resolution\": \"请检查MCHID是否正确\"\n" + | |||||
| " },\n" + | |||||
| " \"REQUIRE_POST_METHOD\": {\n" + | |||||
| " \"detail\": \"请使用post方法\",\n" + | |||||
| " \"reason\": \"未使用post传递参数\",\n" + | |||||
| " \"resolution\": \"请检查请求参数是否通过post方法提交\"\n" + | |||||
| " },\n" + | |||||
| " \"SIGNERROR\": {\n" + | |||||
| " \"detail\": \"签名错误\",\n" + | |||||
| " \"reason\": \"参数签名结果不正确\",\n" + | |||||
| " \"resolution\": \"请检查签名参数和方法是否都符合签名算法要求\"\n" + | |||||
| " },\n" + | |||||
| " \"XML_FORMAT_ERROR\": {\n" + | |||||
| " \"detail\": \"XML格式错误\",\n" + | |||||
| " \"reason\": \"XML格式错误\",\n" + | |||||
| " \"resolution\": \"请检查XML参数格式是否正确\"\n" + | |||||
| " },\n" + | |||||
| " \"FREQUENCY_LIMITED\": {\n" + | |||||
| " \"detail\": \"频率限制\",\n" + | |||||
| " \"reason\": \"2个月之前的订单申请退款有频率限制\",\n" + | |||||
| " \"resolution\": \"该笔退款未受理,请降低频率后重试\"\n" + | |||||
| " }\n" + | |||||
| "}"); | |||||
| private WxRefundOrderP generateWxRefundOrderP(WxPayAccount payAccount,WxAppinfo appInfo,WxRefundOrder record,WxPayOrder payOrder,EnumPayType payType) { | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| WxRefundOrderP wxRefundOrderP = new WxRefundOrderP(); | |||||
| wxRefundOrderP.setAppid(appInfo.getAppId()); | |||||
| wxRefundOrderP.setMch_id(payAccount.getMchId()); | |||||
| wxRefundOrderP.setNonce_str(noncestr); | |||||
| // 微信内部订单号 | |||||
| if (record.getTransactionId() != null) | |||||
| wxRefundOrderP.setTransaction_id(record.getTransactionId()); | |||||
| // 支付订单号 | |||||
| wxRefundOrderP.setOut_trade_no(payOrder.getPayOrderNo()); | |||||
| // 退款支付订单号 | |||||
| wxRefundOrderP.setOut_refund_no(String.valueOf(record.getId())); | |||||
| wxRefundOrderP.setTotal_fee(record.getTotalFee()); | |||||
| wxRefundOrderP.setRefund_fee(record.getRefundFee()); | |||||
| if(null != payType) { | |||||
| if (payType == EnumPayType.PAY_B_REFUND) { | |||||
| wxRefundOrderP.setRefund_desc("B端商户退款"); | |||||
| } else if (payType == EnumPayType.PAY_ADMIN_REFUND) { | |||||
| wxRefundOrderP.setRefund_desc("管理端商户退款"); | |||||
| } else if (payType == EnumPayType.PAY_AUTO_REFUND) { | |||||
| wxRefundOrderP.setRefund_desc("超期自动退款"); | |||||
| } else { | |||||
| wxRefundOrderP.setRefund_desc("用户自己退款"); | |||||
| } | |||||
| } | |||||
| wxRefundOrderP.setNotify_url(payAccount.getRefundNotifyUrl()); | |||||
| return wxRefundOrderP; | |||||
| } | |||||
| private RefundAdapterResult getReusltFromp(String response,WxRefundOrder record,WxPayOrder payOrder) throws MallinkException{ | |||||
| Map<String, String> returnMap = WxPayment.xmlToMap(response); | |||||
| String result_no = returnMap.get("result_code"); | |||||
| String refund_id = returnMap.get("refund_id"); | |||||
| // 设置 微信退款订单号 | |||||
| record.setRefundId(refund_id); | |||||
| record.setRefundVendor(payOrder.getPayVendor()); | |||||
| if ("SUCCESS".equals(result_no)) { | |||||
| log.info("微信退款订单申请成功: " + returnMap.toString()); | |||||
| try { | |||||
| return new RefundAdapterResult(true,EnumRefundStatus.REFUND_REQ_SUCCESS.getCode(),"退款订单申请成功",returnMap); | |||||
| } catch (Exception e) { | |||||
| log.error("微信退款订单更新入库出错: " + e.getMessage() + ", record: " + record.toString()); | |||||
| throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR); | |||||
| } | |||||
| } else { | |||||
| String errDesc = returnMap.get("err_code_des"); | |||||
| if (errDesc.equalsIgnoreCase("订单已全额退款")) { | |||||
| return new RefundAdapterResult(true,EnumRefundStatus.REFUND_REQ_SUCCESS.getCode(),"退款订单申请成功",returnMap); | |||||
| } | |||||
| log.error("微信退款订单申请失败: " + response); | |||||
| String errMsg = ""; | |||||
| JSONObject errObj = errorRefundReqMap.getJSONObject(result_no); | |||||
| if (errObj != null) { | |||||
| errMsg = errObj.toJSONString(); | |||||
| record.setFailReason(errMsg); | |||||
| } else { | |||||
| errMsg = returnMap.get("return_msg"); | |||||
| record.setFailReason(errMsg); | |||||
| } | |||||
| if (errDesc.equalsIgnoreCase("超期订单不允许退款")) { | |||||
| // 更新券状态 | |||||
| throw new MallinkException(ErrorCode.REFUND_NOT_ALLOW); | |||||
| } | |||||
| return new RefundAdapterResult(false, EnumRefundStatus.REFUND_REQ_FAIL.getCode(), errMsg, returnMap); | |||||
| } | |||||
| } | |||||
| private WxRefundOrderSP generateWxRefundOrderSP(WxPayAccount payAccount,WxAppinfo appInfo,WxRefundOrder record,WxPayOrder payOrder,EnumPayType payType) { | |||||
| String noncestr = Utility.generate32UUID(); | |||||
| WxRefundOrderSP wxRefundOrderSP = new WxRefundOrderSP(); | |||||
| wxRefundOrderSP.setAppid(appInfo.getParentAppId()); | |||||
| wxRefundOrderSP.setSub_appid(appInfo.getAppId()); | |||||
| wxRefundOrderSP.setMch_id(payAccount.getMchId()); | |||||
| wxRefundOrderSP.setSub_mch_id(payAccount.getSubMchId()); | |||||
| wxRefundOrderSP.setNonce_str(noncestr); | |||||
| // 微信内部订单号 | |||||
| if (record.getTransactionId() != null) | |||||
| wxRefundOrderSP.setTransaction_id(record.getTransactionId()); | |||||
| // 支付订单号 | |||||
| wxRefundOrderSP.setOut_trade_no(payOrder.getPayOrderNo()); | |||||
| // 退款支付订单号 | |||||
| wxRefundOrderSP.setOut_refund_no(String.valueOf(record.getId())); | |||||
| wxRefundOrderSP.setTotal_fee(record.getTotalFee()); | |||||
| wxRefundOrderSP.setRefund_fee(record.getRefundFee()); | |||||
| if(null != payType) { | |||||
| if (payType == EnumPayType.PAY_B_REFUND) { | |||||
| wxRefundOrderSP.setRefund_desc("B端商户退款"); | |||||
| } else if (payType == EnumPayType.PAY_ADMIN_REFUND) { | |||||
| wxRefundOrderSP.setRefund_desc("管理端商户退款"); | |||||
| } else if (payType == EnumPayType.PAY_AUTO_REFUND) { | |||||
| wxRefundOrderSP.setRefund_desc("超期自动退款"); | |||||
| } else { | |||||
| wxRefundOrderSP.setRefund_desc("用户自己退款"); | |||||
| } | |||||
| } | |||||
| wxRefundOrderSP.setNotify_url(payAccount.getRefundNotifyUrl()); | |||||
| wxRefundOrderSP.setSign_type("HMAC-SHA256"); | |||||
| return wxRefundOrderSP; | |||||
| } | |||||
| private RefundAdapterResult getResultFromSp(String response,WxRefundOrder record,WxPayOrder payOrder) { | |||||
| Map<String, String> returnMap = WxPayment.xmlToMap(response); | |||||
| String result_no = returnMap.get("result_code"); | |||||
| String refund_id = returnMap.get("refund_id"); | |||||
| // 设置 微信退款订单号 | |||||
| record.setRefundId(refund_id); | |||||
| record.setRefundVendor(payOrder.getPayVendor()); | |||||
| if ("SUCCESS".equals(result_no)) { | |||||
| log.info("微信退款订单申请成功: " + returnMap.toString()); | |||||
| try { | |||||
| return new RefundAdapterResult(true, EnumRefundStatus.REFUND_REQ_SUCCESS.getCode(), "退款订单申请成功", returnMap); | |||||
| } catch (Exception e) { | |||||
| log.error("微信退款订单更新入库出错: " + e.getMessage() + ", record: " + record.toString()); | |||||
| throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "订单状态更新失败"); | |||||
| } | |||||
| } else { | |||||
| // 特殊处理 | |||||
| String errDesc = returnMap.get("err_code_des"); | |||||
| if (errDesc.equalsIgnoreCase("订单已全额退款")) { | |||||
| return new RefundAdapterResult(true, EnumRefundStatus.REFUND_REQ_SUCCESS.getCode(), "退款订单申请成功", returnMap); | |||||
| } | |||||
| log.error("微信退款订单申请失败: " + response); | |||||
| String errMsg = ""; | |||||
| JSONObject errObj = errorRefundReqMap.getJSONObject(result_no); | |||||
| if (errObj != null) { | |||||
| errMsg = errObj.toJSONString(); | |||||
| record.setFailReason(errMsg); | |||||
| } else { | |||||
| errMsg = returnMap.get("err_code_des"); | |||||
| record.setFailReason(errMsg); | |||||
| } | |||||
| if (errDesc.equalsIgnoreCase("超期订单不允许退款")) { | |||||
| // 更新券状态 | |||||
| throw new MallinkException(ErrorCode.REFUND_NOT_ALLOW); | |||||
| } | |||||
| return new RefundAdapterResult(false,EnumRefundStatus.REFUND_REQ_FAIL.getCode(),errMsg,returnMap); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public RefundAdapterResult refund(WxPayAccount payAccount,WxAppinfo appInfo,WxRefundOrder record,WxPayOrder payOrder,EnumPayType payType) { | |||||
| if (StringUtils.isBlank(payAccount.getApiKey())) { | |||||
| log.error("支付密钥为空"); | |||||
| throw new MallinkException(ErrorCode.API_KEY_NOT_FOUND.getCode(), "支付密钥为空,请联系商城管理员"); | |||||
| } | |||||
| if (StringUtils.isBlank(payAccount.getCertPath())) { | |||||
| log.error("证书路径为空"); | |||||
| throw new MallinkException(ErrorCode.CERT_PATH_NOT_FOUND.getCode(), "证书路径为空,请联系商城管理员"); | |||||
| } | |||||
| if (!Utility.isFileExist(payAccount.getCertPath())) { | |||||
| log.error("证书文件不存在"); | |||||
| throw new MallinkException(ErrorCode.CERT_PATH_NOT_FOUND.getCode(), "证书文件不存在,请联系商城管理员"); | |||||
| } | |||||
| // 实际支付 | |||||
| // 向微信提交退款申请 | |||||
| if (payAccount.getType() == EnumPayMode.MCH.getCode()) { | |||||
| // 普通商户模式 | |||||
| WxRefundOrderP wxRefundOrderP = generateWxRefundOrderP(payAccount, appInfo, record, payOrder, payType); | |||||
| Map signMap = null; | |||||
| try { | |||||
| signMap = BeanUtils.toStringMap(wxRefundOrderP); | |||||
| } catch (Exception e) { | |||||
| log.error("退款命令生辰: " + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "退款签名异常"); | |||||
| } | |||||
| String signAgent = WxPayment.createSign(signMap, payAccount.getApiKey()); | |||||
| signMap.put("sign", signAgent); | |||||
| String response = null; | |||||
| try { | |||||
| response = WxPay.orderRefund(signMap, payAccount.getCertPath(), payAccount.getMchId()); | |||||
| } catch (Exception e) { | |||||
| log.error("退款异常: " + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "退款异常"); | |||||
| } | |||||
| log.info("微信退款订单:" + wxRefundOrderP.toString() + ", response: " + response.toString()); | |||||
| return getReusltFromp(response, record, payOrder); | |||||
| } else { | |||||
| // 服务商模式 | |||||
| WxRefundOrderSP wxRefundOrderSP = generateWxRefundOrderSP(payAccount, appInfo, record, payOrder, payType); | |||||
| Map signMap = null; | |||||
| try { | |||||
| signMap = BeanUtils.toStringMap(wxRefundOrderSP); | |||||
| } catch (Exception e) { | |||||
| log.error("退款命令生成: " + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), "退款签名异常"); | |||||
| } | |||||
| String signAgent = WxPayment.createSignHMAC(signMap, payAccount.getApiKey()); | |||||
| signMap.put("sign", signAgent); | |||||
| String response = null; | |||||
| try { | |||||
| response = WxPay.orderRefund(signMap, payAccount.getCertPath(), payAccount.getMchId()); | |||||
| } catch (Exception e) { | |||||
| log.error("退款异常: " + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "退款异常"); | |||||
| } | |||||
| log.info("微信退款订单:" + wxRefundOrderSP.toString() + ", response: " + response.toString()); | |||||
| return getResultFromSp(response, record, payOrder); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public RefundAdapterResult queryRefund(WxAppinfo appInfo,WxPayAccount payAccount, WxRefundOrder record) { | |||||
| if (payAccount.getType() == EnumPayMode.MCH.getCode()) { | |||||
| Map<String, String> paramMap = WxPayment.buildWeappRefundQueryMap( | |||||
| appInfo.getAppId(), payAccount.getMchId(), | |||||
| record.getTransactionId(), record.getPayOrderNo(), String.valueOf(record.getId()), | |||||
| record.getRefundId(), payAccount.getApiKey()); | |||||
| String response = WxPay.orderRefundQuery(paramMap); | |||||
| Map<String, String> returnMap = WxPayment.xmlToMap(response); | |||||
| String result_no = returnMap.get("result_code"); | |||||
| if ("SUCCESS".equals(result_no)) { | |||||
| String refund_id = returnMap.get("refund_id"); | |||||
| return new RefundAdapterResult(true,0,"退款",returnMap); | |||||
| } else { | |||||
| String errMsg = ""; | |||||
| JSONObject errObj = errorRefundReqMap.getJSONObject(result_no); | |||||
| if (errObj != null) { | |||||
| errMsg = errObj.toJSONString(); | |||||
| } else { | |||||
| errMsg = returnMap.get("return_msg"); | |||||
| } | |||||
| return new RefundAdapterResult(false,ErrorCode.REFUND_ORDER_ERROR.getCode(),errMsg,returnMap); | |||||
| } | |||||
| } else { | |||||
| Map<String, String> paramMap = WxPayment.buildSWeappRefundQueryMap( | |||||
| appInfo.getParentAppId(), appInfo.getAppId(), payAccount.getMchId(), payAccount.getSubMchId(), | |||||
| record.getTransactionId(), record.getPayOrderNo(), String.valueOf(record.getId()), record.getRefundId(), payAccount.getApiKey()); | |||||
| String response = WxPay.orderRefundQuery(paramMap); | |||||
| Map<String, String> returnMap = WxPayment.xmlToMap(response); | |||||
| String result_no = returnMap.get("result_code"); | |||||
| if ("SUCCESS".equals(result_no)) { | |||||
| String refund_id = returnMap.get("refund_id"); | |||||
| return new RefundAdapterResult(true,0,"退款",returnMap); | |||||
| } else { | |||||
| String errMsg = ""; | |||||
| JSONObject errObj = errorRefundQueryMap.getJSONObject(result_no); | |||||
| if (errObj != null) { | |||||
| errMsg = errObj.toJSONString(); | |||||
| } else { | |||||
| errMsg = returnMap.get("return_msg"); | |||||
| } | |||||
| return new RefundAdapterResult(false,ErrorCode.REFUND_ORDER_ERROR.getCode(),errMsg,returnMap); | |||||
| } | |||||
| } | |||||
| } | |||||
| @Autowired | |||||
| WxAppinfoMapper wxAppinfoMapper; | |||||
| @Autowired | |||||
| WxPayAccountMapper wxPayAccountMapper; | |||||
| @Autowired | |||||
| WxPayOrderMapper wxPayOrderMapper; | |||||
| @Autowired | |||||
| WxRefundOrderMapper wxRefundOrderMapper; | |||||
| private RefundNotifyAdapterResult notifyErrorResult(String msg) { | |||||
| SortedMap resultMap = new TreeMap(); | |||||
| resultMap.put("return_code", "FAIL"); | |||||
| resultMap.put("return_msg", msg); | |||||
| return new RefundNotifyAdapterResult(false,ErrorCode.REFUND_ORDER_ERROR.getCode(),msg,XmlUtil.getRequestXml(resultMap)); | |||||
| } | |||||
| private RefundNotifyAdapterResult notifySuccessResult(String transactionId,String refundId,WxRefundOrder refundOrder) { | |||||
| SortedMap resultMap = new TreeMap(); | |||||
| resultMap.put("return_code", "SUCCESS"); | |||||
| resultMap.put("return_msg", "OK"); | |||||
| return new RefundNotifyAdapterResult(transactionId, refundId,refundOrder,XmlUtil.getRequestXml(resultMap)); | |||||
| } | |||||
| @Override | |||||
| public RefundNotifyAdapterResult notify(Map<String, String> paramMap, EnumPayWay payWay) { | |||||
| // how to get wechatAppId, wechatMchId, partnerKey | |||||
| String appId = paramMap.get("appid"); | |||||
| String subAppId = paramMap.get("sub_appid"); | |||||
| String mchId = paramMap.get("mch_id"); | |||||
| String subMchId = paramMap.get("sub_mch_id"); | |||||
| if (StringUtils.isBlank(subAppId) && StringUtils.isBlank(subMchId)) { | |||||
| // 普通商户号 | |||||
| WxAppinfo appinfo = wxAppinfoMapper.findByAppId(appId); | |||||
| if (appinfo == null) { | |||||
| log.error("未找到appid信息:" + appId); | |||||
| throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND); | |||||
| } | |||||
| WxPayAccount payAccount = wxPayAccountMapper.selectById(appinfo.getPayId()); | |||||
| if (payAccount == null) { | |||||
| log.error("未找到mch_id信息:" + mchId); | |||||
| throw new MallinkException(ErrorCode.MCH_INFO_NOT_FOUND); | |||||
| } | |||||
| if (!mchId.equalsIgnoreCase(payAccount.getMchId())) { | |||||
| log.error("mch_id不对应:" + mchId + ",account:" + payAccount.getMchId()); | |||||
| throw new MallinkException(ErrorCode.MCH_INFO_NOT_EQUAL); | |||||
| } | |||||
| String partnerKey = payAccount.getApiKey(); | |||||
| try { | |||||
| if (payWay.getType() == EnumPayWay.EnumPayWayType.WX_MINIPAY) { | |||||
| if (!"SUCCESS".equals(paramMap.get("return_code"))) { | |||||
| log.warn("notify refund, wxpay status not success, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifyErrorResult("订单状态码非SUCCESS"); | |||||
| } | |||||
| // 解密req_info | |||||
| String req_info = CipherUtil.decryptReqInfo(paramMap.get("req_info"), partnerKey); | |||||
| Map<String, String> reqMap = WxPayment.xmlToMap(req_info); | |||||
| String payOrderNo = reqMap.get("out_trade_no"); | |||||
| Long payOrderId = Long.valueOf(payOrderNo); | |||||
| WxPayOrder payOrder = wxPayOrderMapper.selectById(payOrderId); | |||||
| if (payOrder == null) { | |||||
| log.warn("notify refund, wxpay check pay order not exists, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifyErrorResult("支付订单不存在"); | |||||
| } | |||||
| // 验证支付金额 | |||||
| if (!reqMap.get("total_fee").equals(payOrder.getPayAmount().toString())) { | |||||
| log.warn("notify refund, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifyErrorResult("支付订单总金额不一致"); | |||||
| } | |||||
| String refundIdStr = reqMap.get("out_refund_no"); | |||||
| Long refundOrderId = Long.valueOf(refundIdStr); | |||||
| WxRefundOrder refundOrder = wxRefundOrderMapper.selectById(refundOrderId); | |||||
| if (refundOrder == null) { | |||||
| log.warn("notify refund, wxpay check pay order not exists, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifyErrorResult("退款订单不存在"); | |||||
| } | |||||
| // 验证支付金额 | |||||
| if (!reqMap.get("total_fee").equals(refundOrder.getTotalFee().toString())) { | |||||
| log.warn("notify refund, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifyErrorResult("订单总金额不一致"); | |||||
| } | |||||
| // 验证退款金额 | |||||
| if (!reqMap.get("refund_fee").equals(refundOrder.getRefundFee().toString())) { | |||||
| log.warn("notify refund, wxpay check refund_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifyErrorResult("退款总金额不一致"); | |||||
| } | |||||
| // 处理支付成功 | |||||
| //handleRefundSuccess(refundOrder, reqMap.get("transaction_id"), reqMap.get("refund_id")); | |||||
| log.info("notify refund, wxpay checksign success, paramMap:{}, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifySuccessResult(reqMap.get("transaction_id"), reqMap.get("refund_id"), refundOrder); | |||||
| } | |||||
| } catch (RuntimeException e) { | |||||
| log.warn("notify refund paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| log.warn("notify refund, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } | |||||
| } else { | |||||
| // 服务号回调 | |||||
| WxAppinfo appinfo = wxAppinfoMapper.findByAppId(subAppId); | |||||
| if (appinfo == null) { | |||||
| log.error("未找到appid信息:" + appId); | |||||
| throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND); | |||||
| } | |||||
| WxPayAccount payAccount = wxPayAccountMapper.selectById(appinfo.getPayId()); | |||||
| if (payAccount == null) { | |||||
| log.error("未找到mch_id信息:" + mchId); | |||||
| throw new MallinkException(ErrorCode.MCH_INFO_NOT_FOUND); | |||||
| } | |||||
| if (!mchId.equalsIgnoreCase(payAccount.getMchId())) { | |||||
| log.error("mch_id不对应:" + mchId + ",account:" + payAccount.getMchId()); | |||||
| throw new MallinkException(ErrorCode.MCH_INFO_NOT_EQUAL); | |||||
| } | |||||
| String partnerKey = payAccount.getApiKey(); | |||||
| try { | |||||
| if (payWay.getType() == EnumPayWay.EnumPayWayType.WX_MINIPAY) { | |||||
| if (!"SUCCESS".equals(paramMap.get("return_code"))) { | |||||
| log.warn("notify order, wxpay status not success, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifyErrorResult("订单状态码非SUCCESS"); | |||||
| } | |||||
| // 解密req_info | |||||
| String req_info = CipherUtil.decryptReqInfo(paramMap.get("req_info"), partnerKey); | |||||
| log.info(req_info); | |||||
| Map<String, String> reqMap = WxPayment.xmlToMap(req_info); | |||||
| String payOrderNo = reqMap.get("out_trade_no"); | |||||
| if (payOrderNo == null) { | |||||
| return notifySuccessResult(reqMap.get("transaction_id"), reqMap.get("refund_id"), null); | |||||
| } | |||||
| Long payOrderId = Long.valueOf(payOrderNo); | |||||
| WxPayOrder payOrder = wxPayOrderMapper.selectById(payOrderId); | |||||
| if (payOrder == null) { | |||||
| log.warn("notify refund, wxpay check pay order not exists, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifyErrorResult("支付订单不存在"); | |||||
| } | |||||
| // 验证支付金额 | |||||
| if (!reqMap.get("total_fee").equals(payOrder.getPayAmount().toString())) { | |||||
| log.warn("notify refund, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifyErrorResult("支付订单总金额不一致"); | |||||
| } | |||||
| String refundIdStr = reqMap.get("out_refund_no"); | |||||
| Long refundOrderId = Long.valueOf(refundIdStr); | |||||
| WxRefundOrder refundOrder = wxRefundOrderMapper.selectById(refundOrderId); | |||||
| if (refundOrder == null) { | |||||
| log.warn("notify refund, wxpay check pay order not exists, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifyErrorResult("退款订单不存在"); | |||||
| } | |||||
| // 验证支付金额 | |||||
| if (!reqMap.get("total_fee").equals(refundOrder.getTotalFee().toString())) { | |||||
| log.warn("notify refund, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifyErrorResult("订单总金额不一致"); | |||||
| } | |||||
| // 验证退款金额 | |||||
| if (!reqMap.get("refund_fee").equals(refundOrder.getRefundFee().toString())) { | |||||
| log.warn("notify refund, wxpay check refund_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifyErrorResult("退款总金额不一致"); | |||||
| } | |||||
| log.info("notify refund, wxpay checksign success, paramMap:{}, paramMap: " + reqMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return notifySuccessResult(reqMap.get("transaction_id"), reqMap.get("refund_id"), refundOrder); | |||||
| } | |||||
| } catch (RuntimeException e) { | |||||
| log.warn("notify refund, wepay checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR); | |||||
| } catch (Exception e) { | |||||
| log.warn("notify refund, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), e.getMessage()); | |||||
| } | |||||
| } | |||||
| return notifyErrorResult("FAILED"); | |||||
| } | |||||
| } | |||||
| @@ -1,13 +1,17 @@ | |||||
| package com.iformall.service.pay.service.share; | package com.iformall.service.pay.service.share; | ||||
| import java.util.Map; | |||||
| import com.alibaba.fastjson.JSONArray; | import com.alibaba.fastjson.JSONArray; | ||||
| import com.iformall.domain.po.WxAppinfo; | import com.iformall.domain.po.WxAppinfo; | ||||
| import com.iformall.domain.po.WxPayAccount; | import com.iformall.domain.po.WxPayAccount; | ||||
| import com.iformall.domain.po.WxProfitSharingOrder; | import com.iformall.domain.po.WxProfitSharingOrder; | ||||
| import com.iformall.enums.EnumPayWay; | |||||
| import com.iformall.enums.EnumProfitSharingOrderType; | import com.iformall.enums.EnumProfitSharingOrderType; | ||||
| import com.iformall.enums.EnumProfitSharingReceiverType; | import com.iformall.enums.EnumProfitSharingReceiverType; | ||||
| import com.iformall.exception.MallinkException; | import com.iformall.exception.MallinkException; | ||||
| import com.iformall.service.pay.entity.PayShareResult; | |||||
| import com.iformall.service.pay.service.share.entity.PayShareResult; | |||||
| import com.iformall.service.pay.service.share.entity.ShareNotifyAdapterResult; | |||||
| /** | /** | ||||
| * 分账接口 | * 分账接口 | ||||
| @@ -58,4 +62,7 @@ public interface PayShareAdapterService { | |||||
| */ | */ | ||||
| public EnumProfitSharingReceiverType getShareAccount(Integer accountType); | public EnumProfitSharingReceiverType getShareAccount(Integer accountType); | ||||
| public ShareNotifyAdapterResult notify(Map<String, String> paramMap,EnumPayWay payWay); | |||||
| } | } | ||||
| @@ -1,4 +1,4 @@ | |||||
| package com.iformall.service.pay.entity; | |||||
| package com.iformall.service.pay.service.share.entity; | |||||
| import java.io.Serializable; | import java.io.Serializable; | ||||
| @@ -0,0 +1,76 @@ | |||||
| package com.iformall.service.pay.service.share.entity; | |||||
| import java.io.Serializable; | |||||
| import com.iformall.domain.po.WxPayOrder; | |||||
| public class ShareNotifyAdapterResult implements Serializable{ | |||||
| private static final long serialVersionUID = -6647306162758854293L; | |||||
| private boolean isSuccess; | |||||
| private Integer code; | |||||
| private String msg; | |||||
| private String returnJson; | |||||
| private String transcationId; | |||||
| private WxPayOrder payOrder; | |||||
| public ShareNotifyAdapterResult() { | |||||
| } | |||||
| public ShareNotifyAdapterResult(boolean isSuccess,Integer code,String msg,String returnJson) { | |||||
| this.isSuccess = isSuccess; | |||||
| this.msg = msg; | |||||
| this.returnJson = returnJson; | |||||
| } | |||||
| public ShareNotifyAdapterResult(String transcationId,WxPayOrder payOrder,String returnJson) { | |||||
| this.isSuccess = true; | |||||
| this.transcationId = transcationId; | |||||
| this.payOrder = payOrder; | |||||
| this.returnJson = returnJson; | |||||
| } | |||||
| public boolean isSuccess() { | |||||
| return isSuccess; | |||||
| } | |||||
| public void setSuccess(boolean isSuccess) { | |||||
| this.isSuccess = isSuccess; | |||||
| } | |||||
| public String getMsg() { | |||||
| return msg; | |||||
| } | |||||
| public void setMsg(String msg) { | |||||
| this.msg = msg; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public void setCode(Integer code) { | |||||
| this.code = code; | |||||
| } | |||||
| public String getTranscationId() { | |||||
| return transcationId; | |||||
| } | |||||
| public void setTranscationId(String transcationId) { | |||||
| this.transcationId = transcationId; | |||||
| } | |||||
| public String getReturnJson() { | |||||
| return returnJson; | |||||
| } | |||||
| public void setReturnJson(String returnJson) { | |||||
| this.returnJson = returnJson; | |||||
| } | |||||
| public WxPayOrder getPayOrder() { | |||||
| return payOrder; | |||||
| } | |||||
| public void setPayOrder(WxPayOrder payOrder) { | |||||
| this.payOrder = payOrder; | |||||
| } | |||||
| } | |||||
| @@ -1,28 +1,44 @@ | |||||
| package com.iformall.service.pay.service.share.wx; | package com.iformall.service.pay.service.share.wx; | ||||
| import java.text.ParseException; | |||||
| import java.util.Date; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| import java.util.SortedMap; | |||||
| import java.util.TreeMap; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import com.alibaba.fastjson.JSONArray; | import com.alibaba.fastjson.JSONArray; | ||||
| import com.iformall.common.ErrorCode; | import com.iformall.common.ErrorCode; | ||||
| import com.iformall.domain.po.WxAppinfo; | import com.iformall.domain.po.WxAppinfo; | ||||
| import com.iformall.domain.po.WxPayAccount; | import com.iformall.domain.po.WxPayAccount; | ||||
| import com.iformall.domain.po.WxPayOrder; | |||||
| import com.iformall.domain.po.WxProfitSharingOrder; | import com.iformall.domain.po.WxProfitSharingOrder; | ||||
| import com.iformall.enums.EnumMerchantSubsidyType; | import com.iformall.enums.EnumMerchantSubsidyType; | ||||
| import com.iformall.enums.EnumPayEndFrom; | |||||
| import com.iformall.enums.EnumPayWay; | |||||
| import com.iformall.enums.EnumProfitSharingOrderStatus; | import com.iformall.enums.EnumProfitSharingOrderStatus; | ||||
| import com.iformall.enums.EnumProfitSharingOrderType; | import com.iformall.enums.EnumProfitSharingOrderType; | ||||
| import com.iformall.enums.EnumProfitSharingReceiverType; | import com.iformall.enums.EnumProfitSharingReceiverType; | ||||
| import com.iformall.enums.EnumProfitSharingType; | import com.iformall.enums.EnumProfitSharingType; | ||||
| import com.iformall.exception.MallinkException; | import com.iformall.exception.MallinkException; | ||||
| import com.iformall.mapper.WxAppinfoMapper; | |||||
| import com.iformall.mapper.WxPayAccountMapper; | |||||
| import com.iformall.mapper.WxPayOrderMapper; | |||||
| import com.iformall.pay.WxPayment; | import com.iformall.pay.WxPayment; | ||||
| import com.iformall.pay.WxProfitSharing; | import com.iformall.pay.WxProfitSharing; | ||||
| import com.iformall.pay.WxProfitSharingFinishP; | import com.iformall.pay.WxProfitSharingFinishP; | ||||
| import com.iformall.pay.WxProfitSharingP; | import com.iformall.pay.WxProfitSharingP; | ||||
| import com.iformall.service.pay.entity.PayShareResult; | |||||
| import com.iformall.service.pay.service.share.PayShareAdapterService; | import com.iformall.service.pay.service.share.PayShareAdapterService; | ||||
| import com.iformall.service.pay.service.share.PayShareBaseAdapterService; | import com.iformall.service.pay.service.share.PayShareBaseAdapterService; | ||||
| import com.iformall.service.pay.service.share.entity.PayShareResult; | |||||
| import com.iformall.service.pay.service.share.entity.ShareNotifyAdapterResult; | |||||
| import com.iformall.utils.BeanUtils; | import com.iformall.utils.BeanUtils; | ||||
| import com.iformall.utils.Utility; | import com.iformall.utils.Utility; | ||||
| import com.iformall.utils.XmlUtil; | |||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
| @Slf4j | @Slf4j | ||||
| @@ -130,4 +146,117 @@ public class WxPayShareService extends PayShareBaseAdapterService{ | |||||
| return new PayShareResult(true, null, "success",returnMap, returnMap.get("order_id")); | return new PayShareResult(true, null, "success",returnMap, returnMap.get("order_id")); | ||||
| } | } | ||||
| @Autowired | |||||
| WxAppinfoMapper wxAppinfoMapper; | |||||
| @Autowired | |||||
| WxPayAccountMapper wxPayAccountMapper; | |||||
| @Autowired | |||||
| WxPayOrderMapper wxPayOrderMapper; | |||||
| private ShareNotifyAdapterResult getErrorResult(String msg) { | |||||
| SortedMap resultMap = new TreeMap(); | |||||
| resultMap.put("return_code", "FAIL"); | |||||
| resultMap.put("return_msg", msg); | |||||
| return new ShareNotifyAdapterResult(false,ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR.getCode(),msg,XmlUtil.getRequestXml(resultMap)); | |||||
| } | |||||
| private ShareNotifyAdapterResult getSuccessResult(WxPayOrder payOrder, String transcationId){ | |||||
| SortedMap resultMap = new TreeMap(); | |||||
| resultMap.put("return_code", "SUCCESS"); | |||||
| resultMap.put("return_msg", "OK"); | |||||
| return new ShareNotifyAdapterResult(transcationId, payOrder, XmlUtil.getRequestXml(resultMap)); | |||||
| } | |||||
| @Override | |||||
| public ShareNotifyAdapterResult notify(Map<String, String> paramMap,EnumPayWay payWay) { | |||||
| // how to get wechatAppId, wechatMchId, partnerKey | |||||
| String appId = paramMap.get("appid"); | |||||
| String subAppId = paramMap.get("sub_appid"); | |||||
| String mchId = paramMap.get("mch_id"); | |||||
| String subMchId = paramMap.get("sub_mch_id"); | |||||
| WxAppinfo appinfo = null; | |||||
| boolean isNormal = true; | |||||
| if (StringUtils.isBlank(subAppId) && StringUtils.isBlank(subMchId)) { | |||||
| // 普通商户号 | |||||
| appinfo = wxAppinfoMapper.findByAppId(appId); | |||||
| if (appinfo == null) { | |||||
| log.error("appid not found: " + appId); | |||||
| throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND); | |||||
| } | |||||
| isNormal = true; | |||||
| } else { | |||||
| // 服务号 现在用hmac-sha256 | |||||
| appinfo = wxAppinfoMapper.findByAppId(subAppId); | |||||
| if (appinfo == null) { | |||||
| log.error("subappid not found: " + subAppId); | |||||
| throw new MallinkException(ErrorCode.APP_ID_NOT_FOUND); | |||||
| } | |||||
| isNormal = false; | |||||
| } | |||||
| WxPayAccount payAccount = wxPayAccountMapper.selectById(appinfo.getPayId()); | |||||
| if (payAccount == null) { | |||||
| throw new MallinkException(ErrorCode.MCH_INFO_NOT_FOUND); | |||||
| } | |||||
| String partnerKey = payAccount.getApiKey(); | |||||
| try { | |||||
| if (payWay == EnumPayWay.PAY_WAY_WECHAT) { | |||||
| boolean signVerified = false; | |||||
| if (isNormal) { | |||||
| // 普通商户号支付 | |||||
| signVerified = WxPayment.verifyNotify(paramMap, partnerKey); | |||||
| if (!signVerified) { | |||||
| log.warn("notify order, wxpay checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR); | |||||
| } | |||||
| } else { | |||||
| // 服务号 现在用hmac-sha256 | |||||
| signVerified = WxPayment.verifyNotifyHMAC(paramMap, partnerKey); | |||||
| if (!signVerified) { | |||||
| log.warn("notify order, wxpay checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_NOTIFY_CHECK_SIGN_ERROR); | |||||
| } | |||||
| } | |||||
| if (!"SUCCESS".equals(paramMap.get("return_code"))) { | |||||
| log.warn("notify order, wxpay status not success, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return getErrorResult("订单状态码非SUCCESS"); | |||||
| } | |||||
| String payOrderNo = paramMap.get("out_trade_no"); | |||||
| String timEndStr = paramMap.get("time_end"); | |||||
| Long payOrderId = Long.valueOf(payOrderNo); | |||||
| WxPayOrder payOrder = wxPayOrderMapper.selectById(payOrderId); | |||||
| if (payOrder == null) { | |||||
| log.warn("notify order, wxpay check pay order not exists, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return getErrorResult("订单不存在"); | |||||
| } | |||||
| // 验证支付金额 | |||||
| if (!paramMap.get("total_fee").equals(payOrder.getPayAmount().toString())) { | |||||
| log.warn("notify order, wxpay check total_fee is invalid, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return getErrorResult("订单总金额不一致"); | |||||
| } | |||||
| Date timeEnd = null; | |||||
| try { | |||||
| timeEnd = Utility.getDateFromString(timEndStr); | |||||
| } catch (ParseException e) { | |||||
| log.error("解析timeEnd失败"); | |||||
| timeEnd = new Date(); | |||||
| } | |||||
| payOrder.setPayTimeEnd(timeEnd); | |||||
| log.info("notify order, wxpay checksign success, paramMap:{}, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString()); | |||||
| return getSuccessResult(payOrder, paramMap.get("transaction_id")); | |||||
| } | |||||
| } catch (RuntimeException e) { | |||||
| log.warn("notify order, checksign error, paramMap: " + paramMap.toString() + ", payWay:" + payWay.toString() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.PAY_ORDER_ERROR); | |||||
| } | |||||
| return getErrorResult("FAILED"); | |||||
| } | |||||
| } | } | ||||