xiaoyong931011
2023-04-24 c01d4e141091a009238aabb5692dcb11b7675a45
银行提现、查询
7 files modified
4 files added
842 ■■■■■ changed files
src/main/java/cc/mrbird/febs/mall/dto/AddMemberBankDto.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/UpdateMemberBankDto.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/MallMemberBank.java 6 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/MallMemberWithdrawMsg.java 23 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/MallMemberWithdrawMapper.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/MallMemberWithdrawMsgMapper.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/MemberBankListVo.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/pay/service/NBYHService.java 29 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/pay/service/impl/NBYHServiceImpl.java 738 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/MallMemberWithdrawMapper.xml 7 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/AddMemberBankDto.java
@@ -32,5 +32,14 @@
    // 开户行
    @ApiModelProperty(value = "支行")
    private String subbranchName;
    // 省
    @ApiModelProperty(value = "省")
    private String province;
    // 市
    @ApiModelProperty(value = "市")
    private String city;
    // 收款行号
    @ApiModelProperty(value = "收款行号")
    private String skhh;
}
src/main/java/cc/mrbird/febs/mall/dto/UpdateMemberBankDto.java
@@ -33,4 +33,13 @@
    private String bankName;
    @ApiModelProperty(value = "支行")
    private String subbranchName;
    // 省
    @ApiModelProperty(value = "省")
    private String province;
    // 市
    @ApiModelProperty(value = "市")
    private String city;
    // 收款行号
    @ApiModelProperty(value = "收款行号")
    private String skhh;
}
src/main/java/cc/mrbird/febs/mall/entity/MallMemberBank.java
@@ -24,4 +24,10 @@
    private String digitalNo;
    // 手机号
    private String phone;
    // 省
    private String province;
    // 市
    private String city;
    // 收款行号
    private String skhh;
}
src/main/java/cc/mrbird/febs/mall/entity/MallMemberWithdrawMsg.java
New file
@@ -0,0 +1,23 @@
package cc.mrbird.febs.mall.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("mall_member_withdraw_msg")
public class MallMemberWithdrawMsg extends BaseEntity {
    /**
     * 提现记录ID
     */
    private Long withdrawId;
    /**
     * 提现记录编号
     */
    private String withdrawNo;
    /**
     * 状态 1:已查询 2:未查询
     */
    private Integer status;
}
src/main/java/cc/mrbird/febs/mall/mapper/MallMemberWithdrawMapper.java
@@ -1,6 +1,7 @@
package cc.mrbird.febs.mall.mapper;
import cc.mrbird.febs.mall.entity.MallMemberWithdraw;
import cc.mrbird.febs.mall.entity.MallMemberWithdrawMsg;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
@@ -11,4 +12,5 @@
    List<MallMemberWithdraw> selectListByMemberIdAndDate(@Param("memberId")Long memberId, @Param("date")Date date);
    MallMemberWithdrawMsg selectMsgByWithdrawNo(@Param("withdrawNo")String withdrawNo);
}
src/main/java/cc/mrbird/febs/mall/mapper/MallMemberWithdrawMsgMapper.java
New file
@@ -0,0 +1,7 @@
package cc.mrbird.febs.mall.mapper;
import cc.mrbird.febs.mall.entity.MallMemberWithdrawMsg;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface MallMemberWithdrawMsgMapper extends BaseMapper<MallMemberWithdrawMsg> {
}
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java
@@ -629,6 +629,9 @@
        mallMemberBank.setDigitalNo(updateMemberBankDto.getDigitalNo());
        mallMemberBank.setBankName(updateMemberBankDto.getBankName());
        mallMemberBank.setSubbranchName(updateMemberBankDto.getSubbranchName());
        mallMemberBank.setProvince(updateMemberBankDto.getProvince());
        mallMemberBank.setCity(updateMemberBankDto.getCity());
        mallMemberBank.setSkhh(updateMemberBankDto.getSkhh());
        mallMemberBankMapper.updateById(mallMemberBank);
        return new FebsResponse().success();
    }
src/main/java/cc/mrbird/febs/mall/vo/MemberBankListVo.java
@@ -32,4 +32,13 @@
    @ApiModelProperty(value = "支行")
    private String subbranchName;
    // 省
    @ApiModelProperty(value = "省")
    private String province;
    // 市
    @ApiModelProperty(value = "市")
    private String city;
    // 收款行号
    @ApiModelProperty(value = "收款行号")
    private String skhh;
}
src/main/java/cc/mrbird/febs/pay/service/NBYHService.java
New file
@@ -0,0 +1,29 @@
package cc.mrbird.febs.pay.service;
/**
 * 宁波银企直联接口
 */
public interface NBYHService {
    /**
     * 行内转账
     * @param id 提现ID
     *           1、凭借请求数据,发起银行转账请求
     *           2、生成一条请求记录,
     *           3、定时器循环请求,更新提现记录,直到返回的状态为90,更新状态为成功。
     *
     */
    boolean tradeSinge(Long id);
    /**
     * 跨行汇款
     * @param id 提现ID
     *           1、凭借请求数据,发起银行转账请求
     *           2、生成一条请求记录,
     *           3、定时器循环请求,更新提现记录,直到返回的状态为90,更新状态为成功。
     *
     */
    boolean tradeSingeOuterTransfer(Long id);
    /**
     * 转账结果查询
     */
    void transferResultInfoQuery(String withdrawNo);
}
src/main/java/cc/mrbird/febs/pay/service/impl/NBYHServiceImpl.java
New file
@@ -0,0 +1,738 @@
package cc.mrbird.febs.pay.service.impl;
import cc.mrbird.febs.mall.entity.MallMemberBank;
import cc.mrbird.febs.mall.entity.MallMemberWithdraw;
import cc.mrbird.febs.mall.entity.MallMemberWithdrawMsg;
import cc.mrbird.febs.mall.mapper.MallMemberBankMapper;
import cc.mrbird.febs.mall.mapper.MallMemberWithdrawMapper;
import cc.mrbird.febs.mall.mapper.MallMemberWithdrawMsgMapper;
import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper;
import cc.mrbird.febs.pay.service.NBYHService;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
@Slf4j
@Service
public class NBYHServiceImpl implements NBYHService {
    /**
     * 登录报文原文
     */
    private static final String SIGN_MESSAGE = "<opReq><serialNo>${serialNo}</serialNo><reqTime>${reqTime}</reqTime><ReqParam><userID>0000005332</userID><userPWD>123456</userPWD></ReqParam></opReq>";
    /**
     * 转账报文原文
     */
    private static final String TRADE_MESSAGE_SEARCH = "<opReq><serialNo>${serialNo}</serialNo><reqTime>${reqTime}</reqTime><ReqParam><JYXH>${serialNoOld}</JYXH></ReqParam></opReq>";
    private static final String TRADE_MESSAGE_SINGLE = "<opReq><serialNo>${serialNo}</serialNo><reqTime>${reqTime}</reqTime><ReqParam><FKZH>82260120102022631</FKZH><SKZH>78040122000059277</SKZH><SKHM>792311957</SKHM><JYJE>0.01</JYJE><YOTU>银企接口测试</YOTU></ReqParam></opReq>";
    private static final String TRADE_MESSAGE = "<opReq><serialNo>${serialNo}</serialNo><reqTime>${reqTime}</reqTime><ReqParam><FKZH>${FKZH}</FKZH><SKZH>${SKZH}</SKZH><SKHM>${SKHM}</SKHM><SKYH>${SKYH}</SKYH><SKSH>${SKSH}</SKSH><SKSI>${SKSI}</SKSI><JYJE>${JYJE}</JYJE><YOTU>${YOTU}</YOTU><SKHH>${SKHH}</SKHH></ReqParam></opReq>";
//    private static final String TRADE_MESSAGE = "<opReq><serialNo>${serialNo}</serialNo><reqTime>${reqTime}</reqTime><ReqParam><FKZH>82260120102022631</FKZH><SKZH>6228481060643871117</SKZH><SKHM>王苏平</SKHM><SKYH>中国农业银行舟山市定海支行营业中心</SKYH><SKSH>浙江省</SKSH><SKSI>舟山市</SKSI><JYJE>0.01</JYJE><BIZH>01</BIZH><ZZLX>02</ZZLX><ZZLB>0</ZZLB><YOTU>银企接口测试</YOTU><SKHH>103342040518</SKHH></ReqParam></opReq>";
    /**
     *
     private static final String TRADE_MESSAGE = "<opReq>" +
     "<serialNo>${serialNo}</serialNo>" +
     "<reqTime>${reqTime}</reqTime>" +
     "<ReqParam>" +
     "<FKZH>82260120102022631</FKZH>" +
     "<SKZH>6228481060643871117</SKZH>" +
     "<SKHM>王苏平</SKHM>" +
     "<SKYH>中国农业银行舟山市定海支行营业中心</SKYH>" +
     "<SKSH>浙江省</SKSH>" +
     "<SKSI>舟山市</SKSI>" +
     "<JYJE>0.01</JYJE>" +
     "<YOTU>银企接口测试</YOTU>" +
     "<SKHH>103342040518</SKHH>" +
     "</ReqParam>" +
     "</opReq>";
     跨行转账
     <opReq>
     <serialNo>交易序列号</serialNo>
     <reqTime>客户端请求时间</reqTime>
     <ReqParam>
     <FKZH>付款账号</FKZH>
     <SKZH>收款账号</SKZH>
     <SKHM>收款方户名</SKHM>
     <SKYH>收款账号开户行名称</SKYH>
     <SKSH>收款方行所在省</SKSH>
     <SKSI>收款方行所在市</SKSI>
     <JYJE>交易金额</JYJE>
     <YOTU>用途</YOTU>
     <SKHH>收款行号</SKHH>
     </ReqParam>
     </opReq>
     <opReq><serialNo>${serialNo}</serialNo><reqTime>${reqTime}</reqTime><ReqParam><FKZH>82260120102022631</FKZH><SKZH>6228481060643871117</SKZH><SKHM>王苏平</SKHM><SKYH>中国农业银行舟山市定海支行营业中心</SKYH><SKSH>浙江省</SKSH><SKSI>舟山市</SKSI><JYJE>0.01</JYJE><YOTU>银企接口测试</YOTU><SKHH>103342040518</SKHH></ReqParam></opReq>
     行内转账
     <opReq>
     <serialNo>交易序列号</serialNo>
     <reqTime>客户端请求时间</reqTime>
     <ReqParam>
     <FKZH>付款账号</FKZH>
     <SKZH>收款账号</SKZH>
     <SKHM>收款方户名</SKHM>
     <JYJE>交易金额</JYJE>
     <YOTU>用途</YOTU>
     </ReqParam>
     </opReq>
     <opReq><serialNo>${serialNo}</serialNo><reqTime>${reqTime}</reqTime><ReqParam><FKZH>82260120102022631</FKZH><SKZH>78040122000059277</SKZH><SKHM>792311957</SKHM><JYJE>0.01</JYJE><YOTU>银企接口测试</YOTU></ReqParam></opReq>
     <opReq>
     <serialNo>交易序列号</serialNo>
     <reqTime>客户端请求时间</reqTime>
     <ReqParam>
     <JYXH>原交易序列号</JYXH>
     </ReqParam>
     </opReq>
     <opReq><serialNo>${serialNo}</serialNo><reqTime>${reqTime}</reqTime><ReqParam><JYXH>${serialNoOld}</JYXH></ReqParam></opReq>
     */
    /**
     * 接收报文url
     */
    private static final String URL = "http://127.0.0.1:9080/directlink/httpAccess";
    /**
     * 签名ip
     */
    private static final String VERIFY_IP = "127.0.0.1";
    /**
     * 付款账号
     */
    private static final String FKZH = "82260120102022631";
    /**
     * 签名端口
     */
    private static final int VERIFY_PORT = 8010;
    /**
     * cookies
     */
    private static String cookies = null;
    /**
     * sessionId
     */
    private static String sessionId = "-1";
    /**
     * 客户号
     */
    private static String customerId = "0000005332";
    /**
     * 客户号
     */
    private static String softwareId = "002";
    /**
     * 返回码
     */
    private static String retCode;
    /**
     * 返回信息
     */
    private static String errorMessage;
    public static void main(String[] args) {
        try {
//            System.out.println("发送登录请求:");
//            test.executeServerHttpService("srv001_signOn");
//            System.out.println("\n发送转账结果查询请求:");
//            executeServerHttpService("srv008_transferResultInfoQuery","转账结果查询","2023032910585227466");
//            System.out.println("\n发送跨行转账请求:");
//            test.executeServerHttpService("srv007_singleOuterTransfer","跨行转账",null);
//            System.out.println("\n发送行内转账请求:");
//            executeServerHttpService("srv006_singleInnerTransfer","行内转账","2023032910585227466");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Autowired
    private MallMemberWithdrawMapper mallMemberWithdrawMapper;
    @Autowired
    private MallMemberWithdrawMsgMapper mallMemberWithdrawMsgMapper;
    @Autowired
    private MallMemberBankMapper mallMemberBankMapper;
    @Override
    public boolean tradeSinge(Long id) {
        boolean flag = false;
        MallMemberWithdraw mallMemberWithdraw = mallMemberWithdrawMapper.selectById(id);
        MallMemberBank mallMemberBank = mallMemberBankMapper.selectById(mallMemberWithdraw.getWtihdrawTypeId());
        try {
            String requestDataForWithDraw = getRequestDataForWithDraw("srv006_singleInnerTransfer", "行内转账", mallMemberWithdraw, mallMemberBank);
            String responseStr = executeServerHttpService(requestDataForWithDraw);
            boolean b = parseReturnValueForTrade(responseStr);
            if(b){
                //插入一条记录
                MallMemberWithdrawMsg mallMemberWithdrawMsg = mallMemberWithdrawMapper.selectMsgByWithdrawNo(mallMemberWithdraw.getWithdrawNo());
                if(ObjectUtil.isEmpty(mallMemberWithdrawMsg)){
                    MallMemberWithdrawMsg mallMemberWithdrawMsg1 = new MallMemberWithdrawMsg();
                    mallMemberWithdrawMsg1.setWithdrawNo(mallMemberWithdraw.getWithdrawNo());
                    mallMemberWithdrawMsg1.setWithdrawId(mallMemberWithdraw.getId());
                    mallMemberWithdrawMsg1.setStatus(2);
                    mallMemberWithdrawMsgMapper.insert(mallMemberWithdrawMsg1);
                }
            }
            flag = b;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }
    @Override
    public boolean tradeSingeOuterTransfer(Long id) {
        boolean flag = false;
        MallMemberWithdraw mallMemberWithdraw = mallMemberWithdrawMapper.selectById(id);
        MallMemberBank mallMemberBank = mallMemberBankMapper.selectById(mallMemberWithdraw.getWtihdrawTypeId());
        try {
            String requestDataForWithDraw = getRequestDataForWithDraw("srv007_singleOuterTransfer", "跨行汇款", mallMemberWithdraw, mallMemberBank);
            String responseStr = executeServerHttpService(requestDataForWithDraw);
            boolean b = parseReturnValueForTrade(responseStr);
            if(b){
                //插入一条记录
                MallMemberWithdrawMsg mallMemberWithdrawMsg = mallMemberWithdrawMapper.selectMsgByWithdrawNo(mallMemberWithdraw.getWithdrawNo());
                if(ObjectUtil.isEmpty(mallMemberWithdrawMsg)){
                    MallMemberWithdrawMsg mallMemberWithdrawMsg1 = new MallMemberWithdrawMsg();
                    mallMemberWithdrawMsg1.setWithdrawNo(mallMemberWithdraw.getWithdrawNo());
                    mallMemberWithdrawMsg1.setWithdrawId(mallMemberWithdraw.getId());
                    mallMemberWithdrawMsg1.setStatus(2);
                    mallMemberWithdrawMsgMapper.insert(mallMemberWithdrawMsg1);
                }
            }
            flag = b;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }
    @Override
    public void transferResultInfoQuery(String withdrawNo) {
        MallMemberWithdrawMsg mallMemberWithdrawMsg = mallMemberWithdrawMapper.selectMsgByWithdrawNo(withdrawNo);
        if(ObjectUtil.isEmpty(mallMemberWithdrawMsg)){
            return;
        }
        Integer status = mallMemberWithdrawMsg.getStatus();
        if(1 == status){
            return;
        }
        MallMemberWithdraw mallMemberWithdraw = mallMemberWithdrawMapper.selectById(mallMemberWithdrawMsg.getWithdrawId());
        MallMemberBank mallMemberBank = mallMemberBankMapper.selectById(mallMemberWithdraw.getWtihdrawTypeId());
        try {
            String requestDataForWithDraw = getRequestDataForWithDraw("srv008_transferResultInfoQuery", "转账结果查询", mallMemberWithdraw, mallMemberBank);
            String responseStr = executeServerHttpService(requestDataForWithDraw);
            boolean b = parseReturnValue(responseStr);
            if(b){
                mallMemberWithdrawMsg.setStatus(1);
                mallMemberWithdrawMsgMapper.updateById(mallMemberWithdrawMsg);
            }
            return;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 执行交易
     *
     * @throws Exception
     */
    @SuppressWarnings("rawtypes")
    public static String executeServerHttpService(String requestData) throws Exception {
//    public static void executeServerHttpService(String serviceId, String serviceName, String serialNo,String requestData) throws Exception {
        // 处理交易的url
        java.net.URL url = new URL(URL);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        if (cookies != null) {
            // 如果已登录,设置coikie
            connection.setRequestProperty("cokie", cookies);
        }
        // 请求以utf-8格式编码
        connection.setRequestProperty("content-type", "text/xml;charset=utf-8");
        connection.setDoInput(true);
        connection.setDoOutput(true);
        // post方式发送
        connection.setRequestMethod("POST");
        OutputStream out = connection.getOutputStream();
        // 组装完整的交易报文
//        String reqData = getRequestData(serviceId,serviceName,serialNo);
        String reqData = requestData;
        // utf-8 编码发送
        System.out.println("请求报文:\n" + reqData);
        out.write(reqData.getBytes("UTF-8"));
        out.flush();
        out.close();
        int retCode = connection.getResponseCode();
        if (retCode != 200) {
            throw new Exception("交易出错!retCode=" + retCode);
        }
        // 设置cookie
        Map heads = connection.getHeaderFields();
        Object[] headNames = heads.keySet().toArray();
        for (int i = 0; i < headNames.length; i++) {
            if (headNames[i] == null) {
                continue;
            }
            if ("Set-Cookie".equalsIgnoreCase((String) headNames[i])) {
                cookies = connection.getHeaderField(headNames[i]
                        .toString());
            }
        }
        int len = connection.getContentLength();
        byte[] retData = readContent(connection.getInputStream(), len);
        String retStr = new String(retData, "UTF-8");
        System.out.println("【返回报文】Ret Data:\n " + retStr);
        return retStr;
//        return parseReturnValue(retStr);
    }
    /**
     * 组装完整的报文
     *
     * @param serviceId
     * @return
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static String getRequestData(String serviceId, String serviceName, String serialNo)
            throws FileNotFoundException, IOException {
        StringBuffer buf = new StringBuffer();
        // 报文编码格式utf-8
        buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><NBCBEBankData>");
        buf.append("<sessionId>");
        buf.append(sessionId);
        buf.append("</sessionId>");
        buf.append("<serviceId>");
        buf.append(serviceId);
        buf.append("</serviceId>");
        String reqData = "";
        if (serviceId.equals("srv001_signOn")) {
            reqData = SIGN_MESSAGE;
        } else if (serviceId.equals("srv006_singleInnerTransfer")) {
            reqData = TRADE_MESSAGE_SINGLE;
            /**
             * <opReq><serialNo>${serialNo}</serialNo><reqTime>${reqTime}</reqTime><ReqParam><FKZH>82260120102022631</FKZH><SKZH>78040122000059277</SKZH><SKHM>792311957</SKHM><JYJE>0.01</JYJE><YOTU>银企接口测试</YOTU></ReqParam></opReq>
             * <opReq>
             *     <serialNo>${serialNo}</serialNo>
             *     <reqTime>${reqTime}</reqTime>
             *     <ReqParam>
             *         <FKZH>${FKZH}</FKZH>
             *         <SKZH>${SKZH}</SKZH>
             *         <SKHM>${SKHM}</SKHM>
             *         <JYJE>${JYJE}</JYJE>
             *         <YOTU>${YOTU}</YOTU>
             *     </ReqParam>
             * </opReq>
             */
            reqData = reqData.replaceFirst("\\$\\{FKZH\\}", serialNo);
            reqData = reqData.replaceFirst("\\$\\{SKZH\\}", serialNo);
            reqData = reqData.replaceFirst("\\$\\{SKHM\\}", serialNo);
            reqData = reqData.replaceFirst("\\$\\{JYJE\\}", serialNo);
            reqData = reqData.replaceFirst("\\$\\{YOTU\\}", serialNo);
        }else if (serviceId.equals("srv007_singleOuterTransfer")) {
            reqData = TRADE_MESSAGE;
        }else if (serviceId.equals("srv008_transferResultInfoQuery")) {
            reqData = TRADE_MESSAGE_SEARCH;
            //原订单流水号
            reqData = reqData.replaceFirst("\\$\\{serialNoOld\\}", serialNo);
        }
//        String serialNo = String.valueOf(Math.round(Math.random() * 10000))
//                + System.currentTimeMillis();
        Calendar calendar = Calendar.getInstance();
        Date date = calendar.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String reqTime = sdf.format(date);
        reqData = reqData.replaceFirst("\\$\\{serialNo\\}", serialNo);
        reqData = reqData.replaceFirst("\\$\\{reqTime\\}", reqTime);
        String signData = null;
        try {
            signData = signData(reqData);
            signData = getNodeValue(signData, "signed_data");
        } catch (Exception e) {
            e.printStackTrace();
        }
        buf.append("<customerId>");
        buf.append(customerId);
        buf.append("</customerId>");
        buf.append("<softwareId>");
        buf.append(softwareId);
        buf.append("</softwareId>");
        buf.append("<functionId>");
        buf.append(serviceId.substring(0, 6));
        buf.append("</functionId>");
        buf.append("<functionName>");
        buf.append(serviceName);
        buf.append("</functionName>");
        buf.append(reqData + "<signData>" + signData
                + "</signData></NBCBEBankData>");
        return buf.toString();
    }
    /**
     * 组装完整的报文
     *
     * @param serviceId
     * @return
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static String getRequestDataForWithDraw(String serviceId, String serviceName,MallMemberWithdraw mallMemberWithdraw,MallMemberBank mallMemberBank)
            throws FileNotFoundException, IOException {
        StringBuffer buf = new StringBuffer();
        // 报文编码格式utf-8
        buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><NBCBEBankData>");
        buf.append("<sessionId>");
        buf.append(sessionId);
        buf.append("</sessionId>");
        buf.append("<serviceId>");
        buf.append(serviceId);
        buf.append("</serviceId>");
        String reqData = "";
        if (serviceId.equals("srv001_signOn")) {
            reqData = SIGN_MESSAGE;
        } else if (serviceId.equals("srv006_singleInnerTransfer")) {
            reqData = TRADE_MESSAGE_SINGLE;
            /**
             * <opReq><serialNo>${serialNo}</serialNo><reqTime>${reqTime}</reqTime><ReqParam><FKZH>82260120102022631</FKZH><SKZH>78040122000059277</SKZH><SKHM>792311957</SKHM><JYJE>0.01</JYJE><YOTU>银企接口测试</YOTU></ReqParam></opReq>
             * <opReq>
             *     <serialNo>${serialNo}</serialNo>
             *     <reqTime>${reqTime}</reqTime>
             *     <ReqParam>
             *         <FKZH>${FKZH}</FKZH>
             *         <SKZH>${SKZH}</SKZH>
             *         <SKHM>${SKHM}</SKHM>
             *         <JYJE>${JYJE}</JYJE>
             *         <YOTU>${YOTU}</YOTU>
             *     </ReqParam>
             * </opReq>
             */
            reqData = reqData.replaceFirst("\\$\\{FKZH\\}", FKZH);
            reqData = reqData.replaceFirst("\\$\\{SKZH\\}", mallMemberBank.getBankNo());
            reqData = reqData.replaceFirst("\\$\\{SKHM\\}", mallMemberBank.getName());
            if(mallMemberWithdraw.getRemark().equals("凭证提现")){
                reqData = reqData.replaceFirst("\\$\\{JYJE\\}",
                        mallMemberWithdraw.getAmount().setScale(2, BigDecimal.ROUND_DOWN).toString());
            }else{
                reqData = reqData.replaceFirst("\\$\\{JYJE\\}",
                        mallMemberWithdraw.getAmount().subtract(mallMemberWithdraw.getAmountFee()).setScale(2, BigDecimal.ROUND_DOWN).toString());
            }
            reqData = reqData.replaceFirst("\\$\\{YOTU\\}", "行内转账");
        }else if (serviceId.equals("srv007_singleOuterTransfer")) {
            /**
             * <opReq><serialNo>${serialNo}</serialNo><reqTime>${reqTime}</reqTime><ReqParam><FKZH>82260120102022631</FKZH><SKZH>6228481060643871117</SKZH><SKHM>王苏平</SKHM><SKYH>中国农业银行舟山市定海支行营业中心</SKYH><SKSH>浙江省</SKSH><SKSI>舟山市</SKSI><JYJE>0.01</JYJE><YOTU>银企接口测试</YOTU><SKHH>103342040518</SKHH></ReqParam></opReq>
             * <opReq>
             *     <serialNo>${serialNo}</serialNo>
             *     <reqTime>${reqTime}</reqTime>
             *     <ReqParam>
             *         <FKZH>${FKZH}</FKZH>
             *         <SKZH>${SKZH}</SKZH>
             *         <SKHM>${SKHM}</SKHM>
             *         <SKYH>${SKYH}</SKYH>
             *         <SKSH>${SKSH}</SKSH>
             *         <SKSI>${SKSI}</SKSI>
             *         <JYJE>${JYJE}</JYJE>
             *         <YOTU>${YOTU}</YOTU>
             *         <SKHH>${SKHH}</SKHH>
             *     </ReqParam>
             * </opReq>
             *
             * <opReq><serialNo>${serialNo}</serialNo><reqTime>${reqTime}</reqTime><ReqParam><FKZH>${FKZH}</FKZH><SKZH>${SKZH}</SKZH><SKHM>${SKHM}</SKHM><SKYH>${SKYH}</SKYH><SKSH>${SKSH}</SKSH><SKSI>${SKSI}</SKSI><JYJE>${JYJE}</JYJE><YOTU>${YOTU}</YOTU><SKHH>${SKHH}</SKHH></ReqParam></opReq>
             */
            reqData = TRADE_MESSAGE;
            reqData = reqData.replaceFirst("\\$\\{FKZH\\}", FKZH);
            reqData = reqData.replaceFirst("\\$\\{SKZH\\}", mallMemberBank.getBankNo());
            reqData = reqData.replaceFirst("\\$\\{SKHM\\}", mallMemberBank.getName());
            reqData = reqData.replaceFirst("\\$\\{SKYH\\}", mallMemberBank.getBankName()+mallMemberBank.getSubbranchName());
            reqData = reqData.replaceFirst("\\$\\{SKSH\\}", mallMemberBank.getProvince());
            reqData = reqData.replaceFirst("\\$\\{SKSI\\}", mallMemberBank.getCity());
            if(mallMemberWithdraw.getRemark().equals("凭证提现")){
                reqData = reqData.replaceFirst("\\$\\{JYJE\\}",
                        mallMemberWithdraw.getAmount().setScale(2, BigDecimal.ROUND_DOWN).toString());
            }else{
                reqData = reqData.replaceFirst("\\$\\{JYJE\\}",
                        mallMemberWithdraw.getAmount().subtract(mallMemberWithdraw.getAmountFee()).setScale(2, BigDecimal.ROUND_DOWN).toString());
            }
            reqData = reqData.replaceFirst("\\$\\{YOTU\\}", "跨行汇款");
            reqData = reqData.replaceFirst("\\$\\{SKHH\\}", mallMemberBank.getSkhh());
        }else if (serviceId.equals("srv008_transferResultInfoQuery")) {
            reqData = TRADE_MESSAGE_SEARCH;
            //原订单流水号
            reqData = reqData.replaceFirst("\\$\\{serialNoOld\\}", mallMemberWithdraw.getWithdrawNo());
        }
//        String serialNo = String.valueOf(Math.round(Math.random() * 10000))
//                + System.currentTimeMillis();
        Calendar calendar = Calendar.getInstance();
        Date date = calendar.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String reqTime = sdf.format(date);
        reqData = reqData.replaceFirst("\\$\\{serialNo\\}", mallMemberWithdraw.getWithdrawNo());
        reqData = reqData.replaceFirst("\\$\\{reqTime\\}", reqTime);
        String signData = null;
        try {
            signData = signData(reqData);
            signData = getNodeValue(signData, "signed_data");
        } catch (Exception e) {
            e.printStackTrace();
        }
        buf.append("<customerId>");
        buf.append(customerId);
        buf.append("</customerId>");
        buf.append("<softwareId>");
        buf.append(softwareId);
        buf.append("</softwareId>");
        buf.append("<functionId>");
        buf.append(serviceId.substring(0, 6));
        buf.append("</functionId>");
        buf.append("<functionName>");
        buf.append(serviceName);
        buf.append("</functionName>");
        buf.append(reqData + "<signData>" + signData
                + "</signData></NBCBEBankData>");
        return buf.toString();
    }
    /**
     * 数据加密
     * </br>
     * 重点
     * </br>
     * 1.orignalData.getBytes("GBK").length 获取GBK编码格式的字节长度,为了通过格式验证
     * </br>
     * 2.new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"GBK")); 指定流的编码格式,使加密服务接收到正确的中文字符
     * </br>
     *
     * @param orignalData 原报文体
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String signData(String orignalData)
            throws UnsupportedEncodingException {
        InetAddress addr = null;
        Socket socket = null;
        // 加密报文编码格式gbk
        String verifyheader = "<?xml version=\"1.0\" encoding=\"gbk\"?>\n"
                + "<msg>\n" + "<msg_head>\n" + "<msg_type>0</msg_type>\n"
                + "<msg_id>1005</msg_id>\n" + "<msg_sn>0</msg_sn>\n"
                + "<version>1</version>\n" + "</msg_head>\n" + "<msg_body>\n"
                + "<origin_data_len>" + orignalData.getBytes("GBK").length
                + "</origin_data_len>\n" + "<origin_data>" + orignalData
                + "</origin_data>\n" + "</msg_body>\n" + "</msg>";
        try {
            addr = InetAddress.getByName(VERIFY_IP);
            socket = new Socket(addr, VERIFY_PORT);
            // 发送
            BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(
                    socket.getOutputStream(),"GBK"));
            System.out.println("【数据加密】加密的明文:" + verifyheader);
            wr.write(verifyheader);
            wr.flush();
            // 接收
            BufferedReader rd = new BufferedReader(new InputStreamReader(
                    socket.getInputStream(),"ISO8859-1"));
            String line = null;
            StringBuffer sb = new StringBuffer();
            while ((line = rd.readLine()) != null) {
                sb.append(line);
            }
            // 处理返回
            String returnStr = new String(sb.toString().getBytes("ISO8859-1"),"GBK");
            System.out.println("【数据加密】返回的密文:" + returnStr);
            wr.close();
            rd.close();
            socket.close();
            return returnStr;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }
    /**
     * 从加密返回密文中取出signData
     *
     * @param returnStr
     * @param tagName
     * @return
     */
    public static String getNodeValue(String returnStr, String tagName) {
        int startIdx, endIdx;
        String beginTag = "<" + tagName + ">";
        String endTag = "</" + tagName + ">";
        startIdx = returnStr.indexOf(beginTag) + beginTag.length();
        endIdx = returnStr.indexOf(endTag, startIdx);
        return returnStr.substring(startIdx, endIdx);
    }
    /**
     * 处理返回信息
     *
     * @param src
     * @throws Exception
     */
    public static boolean parseReturnValueForTrade(String src) throws Exception {
        int beginIndex = src.indexOf("<sessionId>");
        int endIndex = src.indexOf("</sessionId>");
        String sessionIdRep = "";
        if (beginIndex != -1 && endIndex != -1) {
            sessionIdRep = src.substring(beginIndex + 11, endIndex);
        }
        if (!sessionIdRep.equals("-1") && !sessionId.equals("-1")
                && !sessionId.equals(sessionIdRep))
//            throw new Exception("上送的sessionId和返回的sessionId不一致! " + src);
            return false;
        if (sessionId.equals("-1"))
            sessionId = sessionIdRep;
        retCode = src.substring(src.indexOf("<retCode>") + 9,
                src.indexOf("</retCode>"));
        String JyztStr = src.substring(src.indexOf("<JYZT>") + 6,
                src.indexOf("</JYZT>"));
        String YddmStr = src.substring(src.indexOf("<YDDM>") + 6,
                src.indexOf("</YDDM>"));
        try {
            errorMessage = src.substring(src.indexOf("<errorMsg>") + 10,
                    src.indexOf("</errorMsg>"));
        } catch (Exception e) {
        }
//        if (retCode == null || !retCode.equals("0000")) {
//            throw new Exception("ServerException: ErrorCode=" + retCode
//                    + " ErrorMessage=" + errorMessage);
//        }
        /**
         * JyztStr
         * 交易成功 90
         * 银行已受理,可通过转账结果查询进行状态查证 94
         * 交易处理中,需过转账结果查询接口进行状态查证 99或者值为空
         *
         * YddmStr
         * 0000或000000表示成功,其他标识失败
         */
        if((JyztStr.equals("90") || JyztStr.equals("94") || JyztStr.equals("99"))
        && (YddmStr.equals("0000") || YddmStr.equals("000000"))){
            return true;
        }else{
            return false;
        }
    }
    /**
     * 处理返回信息
     *
     * @param src
     * @throws Exception
     */
    public static boolean parseReturnValue(String src) throws Exception {
        int beginIndex = src.indexOf("<sessionId>");
        int endIndex = src.indexOf("</sessionId>");
        String sessionIdRep = "";
        if (beginIndex != -1 && endIndex != -1) {
            sessionIdRep = src.substring(beginIndex + 11, endIndex);
        }
        if (!sessionIdRep.equals("-1") && !sessionId.equals("-1")
                && !sessionId.equals(sessionIdRep))
//            throw new Exception("上送的sessionId和返回的sessionId不一致! " + src);
            return false;
        if (sessionId.equals("-1"))
            sessionId = sessionIdRep;
        retCode = src.substring(src.indexOf("<retCode>") + 9,
                src.indexOf("</retCode>"));
        String JyztStr = src.substring(src.indexOf("<JYZT>") + 6,
                src.indexOf("</JYZT>"));
        String YddmStr = src.substring(src.indexOf("<YDDM>") + 6,
                src.indexOf("</YDDM>"));
        try {
            errorMessage = src.substring(src.indexOf("<errorMsg>") + 10,
                    src.indexOf("</errorMsg>"));
        } catch (Exception e) {
        }
//        if (retCode == null || !retCode.equals("0000")) {
//            throw new Exception("ServerException: ErrorCode=" + retCode
//                    + " ErrorMessage=" + errorMessage);
//        }
        /**
         * JyztStr
         * 交易成功 90
         * 银行已受理,可通过转账结果查询进行状态查证 94
         * 交易处理中,需过转账结果查询接口进行状态查证 99或者值为空
         *
         * YddmStr
         * 0000或000000表示成功,其他标识失败
         */
        if((JyztStr.equals("90"))
        && (YddmStr.equals("0000") || YddmStr.equals("000000"))){
            return true;
        }else{
            return false;
        }
    }
    /**
     * 读取返回信息
     *
     * @param in
     * @param len
     * @return
     * @throws IOException
     */
    public static byte[] readContent(InputStream in, int len) throws IOException {
        if (len <= 0) {
            byte[] buf = new byte[2048];
            byte[] readBuf = new byte[1024];
            int totalLen = 0;
            while (true) {
                int readLen = in.read(readBuf);
                if (readLen <= 0)
                    break;
                if (totalLen + readLen > buf.length) {
                    byte[] tmp = new byte[buf.length + readLen + 1024];
                    System.arraycopy(buf, 0, tmp, 0, totalLen);
                    buf = tmp;
                }
                System.arraycopy(readBuf, 0, buf, totalLen, readLen);
                totalLen = totalLen + readLen;
            }
            byte[] retBuf = new byte[totalLen];
            System.arraycopy(buf, 0, retBuf, 0, totalLen);
            return retBuf;
        } else {
            int totalLen = 0;
            byte[] buf = new byte[len];
            while (totalLen < len) {
                int readLen = in.read(buf, totalLen, len - totalLen);
                if (readLen <= 0)
                    break;
                totalLen = totalLen + readLen;
            }
            return buf;
        }
    }
}
src/main/resources/mapper/modules/MallMemberWithdrawMapper.xml
@@ -10,4 +10,11 @@
          and date_format(a.CREATED_TIME, '%Y-%m-%d') = date_format(#{date}, '%Y-%m-%d')
    </select>
    <select id="selectMsgByWithdrawNo" resultType="cc.mrbird.febs.mall.entity.MallMemberWithdrawMsg">
        select
               a.*
        from mall_member_withdraw_msg a
        where a.withdrawNo = #{withdrawNo}
    </select>
</mapper>