| @@ -19,6 +19,7 @@ import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.http.MediaType; | |||
| import org.springframework.web.bind.annotation.PathVariable; | |||
| import org.springframework.web.bind.annotation.RequestMapping; | |||
| import org.springframework.web.bind.annotation.ResponseBody; | |||
| import org.springframework.web.bind.annotation.RestController; | |||
| @@ -125,9 +126,9 @@ public class WxPayController extends BaseController { | |||
| * @return 接收微信异步通知 | |||
| * @throws Exception 可能产生的任何异常 | |||
| */ | |||
| @RequestMapping(value = "/pay/v3", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) | |||
| @RequestMapping(value = "/pay/v3/{tenantId}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) | |||
| @ResponseBody | |||
| public void _payV3Notify(HttpServletRequest request,HttpServletResponse response) throws IOException, JDOMException { | |||
| public void _payV3Notify(@PathVariable String tenantId,HttpServletRequest request,HttpServletResponse response) throws IOException, JDOMException { | |||
| response.setStatus(200); | |||
| } | |||
| @@ -186,8 +187,8 @@ public class WxPayController extends BaseController { | |||
| * @return 接收微信退款异步通知 | |||
| * @throws Exception 可能产生的任何异常 | |||
| */ | |||
| @RequestMapping(value = "/refund/v3") | |||
| public String __refundV3Notify(HttpServletRequest request) throws Exception { | |||
| @RequestMapping(value = "/refund/v3/{tenantId}") | |||
| public String __refundV3Notify(@PathVariable String tenantId,HttpServletRequest request) throws Exception { | |||
| logger.info("[" +getIpAddr() + "]微信退款回调"); | |||
| Map<String, String> paramMap = null; | |||
| String response = ""; | |||
| @@ -275,8 +276,8 @@ public class WxPayController extends BaseController { | |||
| * @return 接收微信分账异步通知 | |||
| * @throws Exception 可能产生的任何异常 | |||
| */ | |||
| @RequestMapping(value = "/sharing/v3") | |||
| public String __shareV3Notify(HttpServletRequest request) throws Exception { | |||
| @RequestMapping(value = "/sharing/v3/{tenantId}") | |||
| public String __shareV3Notify(@PathVariable String tenantId,HttpServletRequest request) throws Exception { | |||
| logger.info("[" +getIpAddr() + "]微信分账回调"); | |||
| Map<String, String> paramMap = null; | |||
| String response = ""; | |||
| @@ -284,8 +285,9 @@ public class WxPayController extends BaseController { | |||
| try { | |||
| xml = IOUtils.toString(request.getInputStream(), Charset.forName("UTF-8")); | |||
| paramMap = WxPayment.xmlToMap(xml); | |||
| paramMap.put("tenantId", tenantId); | |||
| logger.info("share wxpay, notify, param: " + xml ); | |||
| response = wxPayOrderService.shareNotify(paramMap, EnumPayWay.PAY_WAY_WECHAT,EnumPayVersion.WX_PAY_V2); | |||
| response = wxPayOrderService.shareNotify(paramMap, EnumPayWay.PAY_WAY_WECHAT,EnumPayVersion.WX_PAY_V3); | |||
| logger.info("share wxpay, notify success, req : " + xml + ", resp: " + response.toString()); | |||
| return response; | |||
| } catch (BizMessageException e) { | |||
| @@ -26,6 +26,7 @@ import com.iformall.service.WxProfitSharingOrderService; | |||
| import com.iformall.service.pay.PayServiceFactory; | |||
| import com.iformall.service.pay.service.share.PayShareAdapterService; | |||
| import com.iformall.service.pay.service.share.entity.PayShareQueryResult; | |||
| import com.iformall.service.pay.service.share.entity.PayShareQueryResultReceivers; | |||
| import com.iformall.service.pay.service.share.entity.PayShareResult; | |||
| import com.iformall.utils.BeanUtils; | |||
| import com.iformall.utils.DateUtils; | |||
| @@ -359,23 +360,20 @@ public class WxProfitSharingOrderServiceImpl implements WxProfitSharingOrderServ | |||
| return new ResultData(shareResult.getData()); | |||
| } | |||
| String receivers = shareResult.getReceivers(); | |||
| List<PayShareQueryResultReceivers> receivers = shareResult.getReceivers(); | |||
| if (receivers != null) { | |||
| JSONArray jReceivers = JSONArray.parseArray(receivers); | |||
| WxProfitSharingResult result = new WxProfitSharingResult(); | |||
| result.setSharingOrderId(record.getId()); | |||
| result.updateTenantInfo(wxProfitSharingOrder); | |||
| List <WxProfitSharingResult> wxProfitSharingResultList = wxProfitSharingResultMapper.findList(result); | |||
| for(int j = 0; j < jReceivers.size() ; j++) { | |||
| JSONObject res = (JSONObject) jReceivers.get(j); | |||
| for(int j = 0; j < receivers.size() ; j++) { | |||
| PayShareQueryResultReceivers res = receivers.get(j); | |||
| JSONObject des = new JSONObject(); | |||
| des.put("type", res.getString("type")); | |||
| des.put("account", res.getString("account")); | |||
| des.put("description", res.getString("description")); | |||
| des.put("amount", res.getString("amount")); | |||
| des.put("type", res.getType()); | |||
| des.put("account", res.getAccount()); | |||
| des.put("description", res.getDescription()); | |||
| des.put("amount", res.getAmount()); | |||
| int i = 0; | |||
| for (i = 0; i < wxProfitSharingResultList.size(); i++) { | |||
| @@ -383,12 +381,12 @@ public class WxProfitSharingOrderServiceImpl implements WxProfitSharingOrderServ | |||
| WxProfitSharingReceiver wxProfitSharingReceiver = wxProfitSharingReceiverMapper.selectById(wxProfitSharingResult.getSharingReceiverId()); | |||
| if (wxProfitSharingReceiver == null) continue; | |||
| if (res.getString("type").equals(EnumProfitSharingReceiverType.getEnum(wxProfitSharingReceiver.getReceiverType()).getMessage()) | |||
| && res.getString("account").equals(wxProfitSharingReceiver.getReceiverAccount())) { | |||
| wxProfitSharingResult.setFinishTime(res.getString("finish_time")); | |||
| if (res.getType().equals(EnumProfitSharingReceiverType.getEnum(wxProfitSharingReceiver.getReceiverType()).getMessage()) | |||
| && res.getAccount().equals(wxProfitSharingReceiver.getReceiverAccount())) { | |||
| wxProfitSharingResult.setFinishTime(res.getFinish_time()); | |||
| wxProfitSharingResult.setUpdateTime(new Date()); | |||
| wxProfitSharingResult.setSharingStatus(resultStatusMap.getIntValue(res.getString("result"))); | |||
| wxProfitSharingResult.setFailedReason(res.getString("fail_reason")); | |||
| wxProfitSharingResult.setSharingStatus(resultStatusMap.getIntValue(res.getResult())); | |||
| wxProfitSharingResult.setFailedReason(res.getFail_reason()); | |||
| wxProfitSharingResult.setDescription(des.toJSONString()); | |||
| wxProfitSharingResultMapper.updateById(wxProfitSharingResult); | |||
| break; | |||
| @@ -408,10 +406,10 @@ public class WxProfitSharingOrderServiceImpl implements WxProfitSharingOrderServ | |||
| wxProfitSharingResult = list.get(0); | |||
| } | |||
| wxProfitSharingResult.setPayAmount(Integer.valueOf(res.getString("amount"))); | |||
| wxProfitSharingResult.setFinishTime(res.getString("finish_time")); | |||
| wxProfitSharingResult.setSharingStatus(resultStatusMap.getIntValue(res.getString("result"))); | |||
| wxProfitSharingResult.setFailedReason(res.getString("fail_reason")); | |||
| wxProfitSharingResult.setPayAmount(Integer.valueOf(res.getAmount())); | |||
| wxProfitSharingResult.setFinishTime(res.getFinish_time()); | |||
| wxProfitSharingResult.setSharingStatus(resultStatusMap.getIntValue(res.getResult())); | |||
| wxProfitSharingResult.setFailedReason(res.getFail_reason()); | |||
| wxProfitSharingResult.setDescription(des.toJSONString()); | |||
| if (wxProfitSharingResult.getId() != null) { | |||
| wxProfitSharingResult.setUpdateTime(new Date()); | |||
| @@ -1,14 +1,15 @@ | |||
| package com.iformall.service.pay.service.share; | |||
| import java.util.List; | |||
| import com.alibaba.fastjson.JSONArray; | |||
| import com.alibaba.fastjson.JSONObject; | |||
| import com.aliyun.openservices.shade.org.apache.commons.lang3.StringUtils; | |||
| import com.iformall.common.ErrorCode; | |||
| import com.iformall.domain.dto.WxSharingOrderDto; | |||
| import com.iformall.domain.po.WxProfitSharingReceiver; | |||
| import com.iformall.enums.EnumProfitSharingReceiverType; | |||
| import com.iformall.exception.MallinkException; | |||
| import com.iformall.service.pay.service.share.entity.PayShareQueryResultReceivers; | |||
| public abstract class PayShareBaseAdapterService implements PayShareAdapterService{ | |||
| @Override | |||
| @@ -16,6 +17,13 @@ public abstract class PayShareBaseAdapterService implements PayShareAdapterServi | |||
| return EnumProfitSharingReceiverType.getEnum(accountType); | |||
| } | |||
| protected List<PayShareQueryResultReceivers> getReceivers(String response) { | |||
| if (StringUtils.isBlank(response)) { | |||
| return null; | |||
| } | |||
| return JSONArray.parseArray(response,PayShareQueryResultReceivers.class); | |||
| } | |||
| protected String calReceiversAmount(WxSharingOrderDto sharingOrderDto,List<WxProfitSharingReceiver> psReceiverList) { | |||
| if (psReceiverList != null && psReceiverList.size() > 50) { | |||
| throw new MallinkException(ErrorCode.PROFIT_SHARING_RECEIVER_INVALID); | |||
| @@ -1,6 +1,7 @@ | |||
| package com.iformall.service.pay.service.share.entity; | |||
| import java.io.Serializable; | |||
| import java.util.List; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Data; | |||
| @@ -15,7 +16,7 @@ public class PayShareQueryResult implements Serializable{ | |||
| private Integer code; | |||
| private String msg; | |||
| private Object data; | |||
| private String receivers;//数组字符串,平台查询返回的分账账户列表 | |||
| private List<PayShareQueryResultReceivers> receivers;//数组字符串,平台查询返回的分账账户列表 | |||
| @@ -0,0 +1,33 @@ | |||
| package com.iformall.service.pay.service.share.entity; | |||
| import java.io.Serializable; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Data; | |||
| @Data | |||
| public class PayShareQueryResultReceivers implements Serializable{ | |||
| private static final long serialVersionUID = -3701322871877301001L; | |||
| private int amount; | |||
| private String description; | |||
| private String type;//1、MERCHANT_ID:商户号 2、PERSONAL_OPENID:个人openid(由父商户APPID转换得到)3、PERSONAL_SUB_OPENID: 个人sub_openid(由子商户APPID转换得到) | |||
| private String account;//分账接收方账号 | |||
| private String result;//分账结果 | |||
| private String detail_id;//分账明细单号 | |||
| /** | |||
| * 枚举值: | |||
| 1、ACCOUNT_ABNORMAL:分账接收账户异常 | |||
| 2、NO_RELATION:分账关系已解除 | |||
| 3、RECEIVER_HIGH_RISK:高风险接收方 | |||
| 4、RECEIVER_REAL_NAME_NOT_VERIFIED:接收方未实名 | |||
| 5、NO_AUTH:分账权限已解除 | |||
| 6、RECEIVER_RECEIPT_LIMIT:接收方已达收款限额 | |||
| 7、PAYER_ACCOUNT_ABNORMAL:分出方账户异常 | |||
| 8、INVALID_REQUEST: 描述参数设置失败 | |||
| */ | |||
| private String fail_reason;//分账失败原因.当分账结果result为CLOSED(已关闭)时,返回该字段 | |||
| private String create_time;//分账创建时间 | |||
| private String finish_time;//分账完成时间 | |||
| } | |||
| @@ -205,7 +205,7 @@ public class WxPayShareService extends PayShareBaseAdapterService{ | |||
| } | |||
| Integer code = (Integer) statusMap.get(returnMap.get("status")); | |||
| return new PayShareQueryResult(true, code, "success",returnMap, returnMap.get("receivers")); | |||
| return new PayShareQueryResult(true, code, "success",returnMap, getReceivers(returnMap.get("receivers"))); | |||
| } | |||
| @@ -1,5 +1,8 @@ | |||
| package com.iformall.service.pay.service.share.wx.v3; | |||
| import java.io.IOException; | |||
| import java.security.GeneralSecurityException; | |||
| import java.text.ParseException; | |||
| import java.util.*; | |||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||
| import com.github.binarywang.wxpay.exception.WxPayException; | |||
| @@ -23,6 +26,7 @@ import com.iformall.exception.MallinkException; | |||
| import com.iformall.pay.WxPayV3; | |||
| import com.iformall.pay.WxPayment; | |||
| import com.iformall.pay.WxProfitSharing; | |||
| import com.iformall.service.WxPayAccountService; | |||
| import com.iformall.service.WxProfitSharingReceiverService; | |||
| import com.iformall.service.order.util.OrderHelper; | |||
| import com.iformall.service.pay.service.share.PayShareBaseAdapterService; | |||
| @@ -36,6 +40,7 @@ import com.iformall.service.pay.service.share.wx.v3.entity.V3PayShareReq; | |||
| import com.iformall.service.pay.service.share.wx.v3.entity.V3PayShareUnfreezeReq; | |||
| import com.iformall.utils.BeanUtils; | |||
| import com.iformall.utils.MaUtil; | |||
| import com.iformall.utils.Utility; | |||
| import com.iformall.utils.XmlUtil; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| @@ -53,6 +58,10 @@ public class WxPayShareV3Service extends PayShareBaseAdapterService{ | |||
| @Autowired | |||
| MaUtil maUtil; | |||
| @Lazy | |||
| @Autowired | |||
| WxPayAccountService wxPayAccountService; | |||
| @Override | |||
| public Integer getSubsidyType() { | |||
| @@ -137,7 +146,7 @@ public class WxPayShareV3Service extends PayShareBaseAdapterService{ | |||
| req.setSub_mchid(payAccount.getSubMchId()); | |||
| } | |||
| req.setTransaction_id(transcationId); | |||
| req.setOut_order_no(String.valueOf(record.getId())); | |||
| req.setOut_order_no(String.valueOf(record.getOrderId())); | |||
| req.setDescription(appInfo.getName()+"支付订单:"+record.getOrderId()); | |||
| WxPayService payService = maUtil.getWxPayService(appInfo, payAccount); | |||
| @@ -169,7 +178,7 @@ public class WxPayShareV3Service extends PayShareBaseAdapterService{ | |||
| req.setAppid(appInfo.getParentAppId()); | |||
| req.setSub_appid(appInfo.getAppId()); | |||
| req.setTransaction_id(transcationId); | |||
| req.setOut_order_no(String.valueOf(record.getId())); | |||
| req.setOut_order_no(String.valueOf(record.getOrderId())); | |||
| req.setReceivers(receivers); | |||
| WxPayService payService = maUtil.getWxPayService(appInfo, payAccount); | |||
| String response = null; | |||
| @@ -199,7 +208,7 @@ public class WxPayShareV3Service extends PayShareBaseAdapterService{ | |||
| req.setSub_mchid(payAccount.getSubMchId()); | |||
| } | |||
| req.setTransaction_id(record.getTransactionId()); | |||
| req.setOut_order_no(String.valueOf(record.getId())); | |||
| req.setOut_order_no(String.valueOf(record.getOrderId())); | |||
| WxPayService payService = maUtil.getWxPayService(appInfo, payAccount); | |||
| String response = null; | |||
| try { | |||
| @@ -220,8 +229,7 @@ public class WxPayShareV3Service extends PayShareBaseAdapterService{ | |||
| if (StringUtils.isBlank(out_order_no) || !out_order_no.equals(record.getId().toString())){ | |||
| throw new MallinkException(ErrorCode.PROFIT_SHARING_QUERY_RETURN_INVALID.getCode(),"out_order_no:["+out_order_no+"] WxProfitSharingOrder:["+record.getId()+"]"); | |||
| } | |||
| 111111111111111 | |||
| return new PayShareQueryResult(true, 200, "success",result, JSON.toJSONString(result.get("receivers"))); | |||
| return new PayShareQueryResult(true, 200, "success",result, this.getReceivers(JSON.toJSONString(result.get("receivers")))); | |||
| } | |||
| @@ -248,9 +256,57 @@ public class WxPayShareV3Service extends PayShareBaseAdapterService{ | |||
| @Override | |||
| public ShareNotifyAdapterResult notify(Map<String, String> paramMap,EnumPayWay payWay) { | |||
| String tenantId = paramMap.get("tenantId"); | |||
| String resource = paramMap.get("resource"); | |||
| JSONObject reObj = JSON.parseObject(resource); | |||
| WxPayService wxPayService = wxPayAccountService.getWxPayService(tenantId); | |||
| try { | |||
| String decryptContent = WxPayV3.decrypt(wxPayService, reObj.getString("ciphertext"), reObj.getString("nonce"), reObj.getString("associated_data")); | |||
| JSONObject decryptObj = JSON.parseObject(decryptContent); | |||
| String spMchId = decryptObj.getString("sp_mchid"); | |||
| String subMchId = decryptObj.getString("sub_mchid"); | |||
| String transactionId = decryptObj.getString("transaction_id"); | |||
| String orderId = decryptObj.getString("order_id"); | |||
| String outOrderNo = decryptObj.getString("out_order_no"); | |||
| String successTime = decryptObj.getString("success_time"); | |||
| JSONObject rObj = decryptObj.getJSONObject("receiver"); | |||
| String type = rObj.getString("type"); | |||
| String account = rObj.getString("account"); | |||
| int amount = rObj.getIntValue("amount"); | |||
| String description = rObj.getString("description"); | |||
| Long payOrderId = Long.valueOf(outOrderNo); | |||
| WxPayOrder payOrder = wxPayOrderMapper.selectById(payOrderId,tenantId); | |||
| 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; | |||
| return getErrorResult("FAILED"); | |||
| try { | |||
| timeEnd = Utility.getDateFromString(successTime); | |||
| } 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, transactionId); | |||
| } catch (GeneralSecurityException e1) { | |||
| log.error("pay v3 share nofify error.",e1); | |||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"分账通知错误"+e1.getMessage()); | |||
| } catch (IOException e1) { | |||
| log.error("pay v3 share nofify error.",e1); | |||
| throw new MallinkException(ErrorCode.SYS_SERVER_ERROR.getCode(),"分账通知错误"+e1.getMessage()); | |||
| } | |||
| } | |||
| @Override | |||