diff --git a/mallinkBApi/src/main/java/com/iformall/controller/WxCashOutController.java b/mallinkBApi/src/main/java/com/iformall/controller/WxCashOutController.java index c6b953843..331a30946 100644 --- a/mallinkBApi/src/main/java/com/iformall/controller/WxCashOutController.java +++ b/mallinkBApi/src/main/java/com/iformall/controller/WxCashOutController.java @@ -58,5 +58,27 @@ public class WxCashOutController extends BaseController { return wxCashOutService.applyCashout(buser, wxCashOut,EnumPayWay.PAY_WAY_WECHAT); } + + @ApiOperation("微信B端重新提现") + @PostMapping("recashout") + public ResultData recashout(@RequestBody WxCashOut wxCashOut) { + WxMerchantBUser buser = getLoginBUser(); + //当前管理员的账户必须在c端授权了 + WxCUser cuUser = new WxCUser(); + cuUser.updateTenantInfo(buser); + cuUser.setPhone(buser.getPhone()); + try { + WxCUser mUser = wxCUserService.getByObject(cuUser); + if (mUser == null) { + return new ResultData(Result.ERROR,"请用绑定["+buser.getPhone()+"]的微信在C端完成授权手机号操作。"); + } + wxCashOut.setReciveOpenId(mUser.getOpenId()); + wxCashOut.setReciveNickName(mUser.getNickName()); + }catch(Exception e) { + return new ResultData(Result.ERROR,buser.getPhone()+"匹配C端用户失败,该情况可能是存在多个微信对应统一手机号,请联系管理员处理, 。"); + } + + return wxCashOutService.reCashout(buser, wxCashOut,EnumPayWay.PAY_WAY_WECHAT); + } } diff --git a/mallinkService/src/main/java/com/iformall/pay/WxCashOutQueryP.java b/mallinkService/src/main/java/com/iformall/pay/WxCashOutQueryP.java new file mode 100644 index 000000000..db38da489 --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/pay/WxCashOutQueryP.java @@ -0,0 +1,27 @@ +package com.iformall.pay; + +import lombok.Data; + +/** + * Created by Stormeye on 2018/8/10. + */ +@Data +public class WxCashOutQueryP { + private String appid; // 申请商户号的appid或商户号绑定的appid + private String mch_id; // 商户号 + private String nonce_str; // 随机字符串 + private String sign; // 签名 + private String partner_trade_no; // 商户订单号,需保持唯一性 (只能是字母或者数字,不能包含有其它字符) + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("WxCashOutQueryP{"); + sb.append("appid='").append(appid).append('\''); + sb.append(", mch_id='").append(mch_id).append('\''); + sb.append(", nonce_str='").append(nonce_str).append('\''); + sb.append(", sign='").append(sign).append('\''); + sb.append(", partner_trade_no='").append(partner_trade_no).append('\''); + sb.append('}'); + return sb.toString(); + } +} diff --git a/mallinkService/src/main/java/com/iformall/service/WxCashOutService.java b/mallinkService/src/main/java/com/iformall/service/WxCashOutService.java index 69c89e36e..53e6f24c5 100644 --- a/mallinkService/src/main/java/com/iformall/service/WxCashOutService.java +++ b/mallinkService/src/main/java/com/iformall/service/WxCashOutService.java @@ -42,4 +42,10 @@ public interface WxCashOutService { void rejectCashOut(WxCashOut record); void cashOutToWx(EnumPayWay payWay,TenantEntity tenantEntity, Long cashOutId); + + /** + * 失败的情况下,可以重复发起 + */ + ResultData reCashout(WxMerchantBUser buser,WxCashOut record,EnumPayWay payWay); + } diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxCashOutServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxCashOutServiceImpl.java index 5c0f667fc..c59667a06 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxCashOutServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxCashOutServiceImpl.java @@ -240,4 +240,47 @@ public class WxCashOutServiceImpl implements WxCashOutService { } wxCashOutMapper.updateById(cashout); } + + @Override + public ResultData reCashout(WxMerchantBUser buser, WxCashOut record, EnumPayWay payWay) { + WxCashOut cashout = this.getById(record.getId(), buser.getTenantId()); + if (null == cashout ) { + return new ResultData(Result.ERROR,"该提现记录不存在"); + } + + if( EnumCashOutStatus.FAIL.getCode().intValue() != record.getStatus().intValue()) { + return new ResultData(Result.ERROR,"提现失败状态才能重新提现。"); + } + + //只有商户管理员才能进行此操作 + WxMerchant merchant = wxMerchantMapper.selectById(buser.getMerchantId()); + if (!(buser.getPhone().equals(merchant.getLinkPhone()))) { + return new ResultData(Result.ERROR,"当前账号非商户管理员,不能进行此操作。"); + } + WxAppinfo appInfo = wxAppinfoService.getCAppInfo(buser, payWay); + if (null == appInfo) { + return new ResultData(Result.ERROR,"当前账号非商户管理员,不能进行此操作。"); + } + WxPayAccount payAccount = wxPayAccountService.getByTenantId(buser.getTenantId()); + if (null == payAccount) { + return new ResultData(Result.ERROR,"当前账号非商户管理员,不能进行此操作。"); + } + //查询是否已经真实的转过了 + CashOutAdapterResult qresult = payServiceFactory.getCashOutAdapterService(payWay.getCode()).queryCashOut(appInfo, payAccount, cashout); + if (qresult.isSuccess()) { + cashout.setStatus(EnumCashOutStatus.SUCCESS.getCode()); + wxCashOutMapper.updateStatus(cashout); + }else { + CashOutAdapterResult result = payServiceFactory.getCashOutAdapterService(payWay.getCode()).cashOut(appInfo, payAccount, cashout); + cashout.setUpdateDate(new Date()); + if (result.isSuccess()) { + cashout.setStatus(EnumCashOutStatus.SUCCESS.getCode()); + }else { + cashout.setStatus(EnumCashOutStatus.FAIL.getCode()); + cashout.setFailRemark(result.getMsg()); + } + wxCashOutMapper.updateById(cashout); + } + return new ResultData(); + } } diff --git a/mallinkService/src/main/java/com/iformall/service/pay/service/cashout/CashOutAdapterService.java b/mallinkService/src/main/java/com/iformall/service/pay/service/cashout/CashOutAdapterService.java index dcb9d87ec..b0f2161b2 100644 --- a/mallinkService/src/main/java/com/iformall/service/pay/service/cashout/CashOutAdapterService.java +++ b/mallinkService/src/main/java/com/iformall/service/pay/service/cashout/CashOutAdapterService.java @@ -34,4 +34,15 @@ public interface CashOutAdapterService { * @return */ public CashOutAdapterResult cashOut(WxAppinfo appInfo,WxPayAccount payAccount,WxCashOut cashOut); + + /** + * 付款到零钱 + * @param appInfo + * @param payAccount + * @param record + * @param transcationId + * @param amount 分账金额 + * @return + */ + public CashOutAdapterResult queryCashOut(WxAppinfo appInfo,WxPayAccount payAccount,WxCashOut cashOut); } diff --git a/mallinkService/src/main/java/com/iformall/service/pay/service/cashout/wx/WxCashOutAdapterService.java b/mallinkService/src/main/java/com/iformall/service/pay/service/cashout/wx/WxCashOutAdapterService.java index f44f9a1f4..1ced7f489 100644 --- a/mallinkService/src/main/java/com/iformall/service/pay/service/cashout/wx/WxCashOutAdapterService.java +++ b/mallinkService/src/main/java/com/iformall/service/pay/service/cashout/wx/WxCashOutAdapterService.java @@ -30,6 +30,7 @@ import com.iformall.mapper.WxPayAccountMapper; import com.iformall.mapper.WxPayOrderMapper; import com.iformall.mapper.WxRefundOrderMapper; import com.iformall.pay.WxCashOutP; +import com.iformall.pay.WxCashOutQueryP; import com.iformall.pay.WxPay; import com.iformall.pay.WxPayment; import com.iformall.pay.WxRefundOrderP; @@ -148,7 +149,45 @@ public class WxCashOutAdapterService implements CashOutAdapterService{ " }\n" + "}"); - + JSONObject errorQueryReqMap = JSON.parseObject("{\n" + + " \"CA_ERROR\": {\n" + + " \"detail\": \"请求未携带证书,或请求携带的证书出错\",\n" + + " \"reason\": \"请求未携带证书,或请求携带的证书出错\",\n" + + " \"resolution\": \"到商户平台下载证书,请求带上证书后重试。\"\n" + + " },\n" + + " \"SIGN_ERROR\": {\n" + + " \"detail\": \"商户签名错误\",\n" + + " \"reason\": \"商户签名错误\",\n" + + " \"resolution\": \"按文档要求重新生成签名后再重试。\"\n" + + " },\n" + + " \"FREQ_LIMIT\": {\n" + + " \"detail\": \"受频率限制\",\n" + + " \"reason\": \"受频率限制\\t\",\n" + + " \"resolution\": \"请对请求做频率控制\"\n" + + " },\n" + + " \"XML_ERROR\": {\n" + + " \"detail\": \"请求的xml格式错误,或者post的数据为空\",\n" + + " \"reason\": \"请求的xml格式错误,或者post的数据为空\",\n" + + " \"resolution\": \"检查请求串,确认无误后重试。\"\n" + + " },\n" + + " \"PARAM_ERROR\": {\n" + + " \"detail\": \"参数错误\",\n" + + " \"reason\": \"参数错误\",\n" + + " \"resolution\": \"请查看err_code_des,修改设置错误的参数。\"\n" + + " },\n" + + " \"SYSTEMERROR\": {\n" + + " \"detail\": \"系统繁忙,请再试\",\n" + + " \"reason\": \"系统繁忙,请再试\\t\",\n" + + " \"resolution\": \"系统繁忙\"\n" + + " },\n" + + " \"NOT_FOUND\": {\n" + + " \"detail\": \"1、指定单号数据不存在 2、指定单号数据不存在,单据查询超过有效期\",\n" + + " \"reason\": \"1、指定单号数据不存在 2、指定单号数据不存在,单据查询超过有效期\",\n" + + " \"resolution\": \"1、查询单号对应的数据不存在,请使用正确的商户订单号查询2、如需查询超过有效期的单据,请登录到商户平台进行查询。\"\n" + + " }\n" + + "}"); + + @Override public CashOutAdapterResult cashOut(WxAppinfo appInfo, WxPayAccount payAccount, WxCashOut cashOut) { WxCashOutP wxCashOutP = generateWxCashOutP(payAccount, appInfo, cashOut); @@ -213,4 +252,63 @@ public class WxCashOutAdapterService implements CashOutAdapterService{ return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), errMsg, returnMap); } } + + @Override + public CashOutAdapterResult queryCashOut(WxAppinfo appInfo, WxPayAccount payAccount, WxCashOut cashOut) { + WxCashOutQueryP wxCashOutP = generateQueryWxCashOutP(payAccount, appInfo, cashOut); + Map signMap = null; + try { + signMap = BeanUtils.toStringMap(wxCashOutP); + } catch (Exception e) { + log.error("零钱支付命令生辰: " + e.getMessage(),e); + 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.getTransferInfo(signMap, payAccount.getCertPath(), payAccount.getMchId()); + } catch (Exception e) { + log.error("零钱支付异常: " + e.getMessage(),e); + throw new MallinkException(ErrorCode.REFUND_ORDER_ERROR.getCode(), "零钱支付异常"); + } + log.info("微信零钱支付:" + wxCashOutP.toString() + ", response: " + response.toString()); + return getReusltFromQueryp(response); + } + + private WxCashOutQueryP generateQueryWxCashOutP(WxPayAccount payAccount,WxAppinfo appInfo,WxCashOut cashOut) { + String noncestr = Utility.generate32UUID(); + WxCashOutQueryP wxCashOutQueryP = new WxCashOutQueryP(); + wxCashOutQueryP.setAppid(appInfo.getAppId()); + wxCashOutQueryP.setMch_id(payAccount.getSubMchId()); + wxCashOutQueryP.setNonce_str(noncestr); + wxCashOutQueryP.setPartner_trade_no(String.valueOf(cashOut.getId())); + return wxCashOutQueryP; + } + + private CashOutAdapterResult getReusltFromQueryp(String response) throws MallinkException{ + Map returnMap = WxPayment.xmlToMap(response); + String result_no = returnMap.get("result_code"); + if ("SUCCESS".equals(result_no)) { + String realStatus = returnMap.get("status"); + if ("SUCCESS".equals(realStatus)) { + return new CashOutAdapterResult(true,EnumCashOutStatus.SUCCESS.getCode(),"微信零钱支付申请成功",returnMap); + }else { + String msg = returnMap.get("reason"); + return new CashOutAdapterResult(false,EnumCashOutStatus.SUCCESS.getCode(),msg,returnMap); + } + } else { + log.error("微信零钱支付查询失败: " + response); + String errMsg = ""; + JSONObject errObj = errorQueryReqMap.getJSONObject(result_no); + if (errObj != null) { + errMsg = errObj.toJSONString(); + } else { + errMsg = returnMap.get("err_code_des"); + } + return new CashOutAdapterResult(false, EnumCashOutStatus.FAIL.getCode(), errMsg, returnMap); + } + } + }