<NME> FuiouPayService.java
<BEF> package com.egzosn.pay.fuiou.api;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.common.api.BasePayService;
import com.egzosn.pay.common.api.Callback;
import java.util.HashMap;
import com.egzosn.pay.common.bean.*;
import com.egzosn.pay.common.exception.PayErrorException;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.common.util.sign.SignUtils;
import com.egzosn.pay.common.util.str.StringUtils;
import org.apache.commons.logging.Log;
import com.egzosn.pay.common.bean.MethodType;
import com.egzosn.pay.common.bean.NoticeParams;
import com.egzosn.pay.common.bean.NoticeRequest;
import com.egzosn.pay.common.bean.OrderParaStructure;
import com.egzosn.pay.common.bean.PayMessage;
import com.egzosn.pay.common.bean.PayOrder;
import com.egzosn.pay.common.bean.PayOutMessage;
import com.egzosn.pay.common.bean.RefundOrder;
import com.egzosn.pay.common.bean.RefundResult;
import com.egzosn.pay.common.bean.TransactionType;
import com.egzosn.pay.common.exception.PayErrorException;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.common.http.UriVariables;
import com.egzosn.pay.common.util.DateUtils;
import com.egzosn.pay.common.util.Util;
import com.egzosn.pay.common.util.sign.SignTextUtils;
import com.egzosn.pay.common.util.sign.SignUtils;
import com.egzosn.pay.common.util.str.StringUtils;
import com.egzosn.pay.fuiou.bean.FuiouRefundResult;
import com.egzosn.pay.fuiou.bean.FuiouTransactionType;

/**
 * @author Actinia
 * <pre>
 * email hayesfu@qq.com
 * create 2017 2017/1/16 0016
 * </pre>
 */
public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {

    /**
     * 正式域名
     */
    public static final String URL_FUIOU_BASE_DOMAIN = "https://pay.fuiou.com/";
    /**
     * 测试域名
     */
    public static final String DEV_URL_FUIOU_BASE_DOMAIN = "http://www-1.fuiou.com:8888/wg1_run/";

    /**
     * B2C/B2B支付
     */
    public static final String URL_FuiouSmpGate = "smpGate.do";
    /**
     * B2C/B2B支付(跨境支付)
     */
    public static final String URL_FuiouNewSmpGate = "newSmpGate.do";
    /**
     * 订单退款
     */
    public static final String URL_FuiouSmpRefundGate = "newSmpRefundGate.do";
    /**
     * 3.2	支付结果查询
     */
    public static final String URL_FuiouSmpQueryGate = "smpQueryGate.do";
    /**
     * 3.3	支付结果查询(直接返回)
     */
    public static final String URL_FuiouSmpAQueryGate = "smpAQueryGate.do";
    /**
     * 3.4订单退款
     */
    public static final String URL_NewSmpRefundGate = "newSmpRefundGate.do";
    /**
     * 异步通知
     */
    public static final String BACK_NOTIFY_URL = "back_notify_url";


    /**
     * 获取对应的请求地址
     *
     * @return 请求地址
     */
    @Override
    public String getReqUrl(TransactionType transactionType) {
        return payConfigStorage.isTest() ? DEV_URL_FUIOU_BASE_DOMAIN : URL_FUIOU_BASE_DOMAIN;
    }

    /**
     * 获取对应的请求地址
     *
     * @return 请求地址
     */
    public String getReqUrl() {
        return getReqUrl(null);
    }

    @Override
    public boolean signVerify(Map<String, Object> params, String responseSign) {

        params = new LinkedHashMap<>(params);

        String sign = createSign(SignUtils.parameters2MD5Str(params, "|"), payConfigStorage.getInputCharset());

        return responseSign.equals(sign);
    public FuiouPayService(FuiouPayConfigStorage payConfigStorage, HttpConfigStorage configStorage) {
        super(payConfigStorage, configStorage);
    }

    /**
     * 构造函数，初始化时候使用
     *
     * @param payConfigStorage 支付账户配置信息
     */
    public FuiouPayService(FuiouPayConfigStorage payConfigStorage) {
        super(payConfigStorage);
        params.put("mchnt_cd", payConfigStorage.getPid());
        params.put("order_id", order_id);
        params.put("md5", createSign(SignUtils.parameters2MD5Str(params, "|"), payConfigStorage.getInputCharset()));
        JSONObject resultJson = getHttpRequestTemplate().postForObject(getReqUrl() + URL_FuiouSmpAQueryGate, params, JSONObject.class);
        return "0000".equals(resultJson.getString("order_pay_code"));
    }

    /**
     * 将支付请求参数加密成md5
     * @param order 支付订单
    }

    /**
     * 回调校验
     *
     * @param noticeParams 回调回来的参数集
     * @return 签名校验 true通过
     */
    @Override
    public boolean verify(NoticeParams noticeParams) {
        final Map<String, Object> params = noticeParams.getBody();
        if (!"0000".equals(params.get("order_pay_code"))) {
            LOG.debug(String.format("富友支付异常：order_pay_code=%s,错误原因=%s,参数集=%s", params.get("order_pay_code"), params.get("order_pay_error"), params));
            return false;
        }
        try {
            //返回参数校验  和 重新请求订单检查数据是否合法
            return (signVerify(params, (String) params.remove("md5")) && verifySource((String) params.get("order_id")));
        }
        catch (PayErrorException e) {
            LOG.error("", e);
        }
        return false;
    }

    /**
     * 回调签名校验
     *
     * @param params       参数集
     * @param responseSign 响应的签名串
     * @return 校验结果
     */
    public boolean signVerify(Map<String, Object> params, String responseSign) {

        String sign = createSign(SignTextUtils.parameters2Md5Str(params, "|"), payConfigStorage.getInputCharset());

        return responseSign.equals(sign);
    }
     */
    @Override
    public String createSign(String content, String characterEncoding) {
        return SignUtils.valueOf(payConfigStorage.getSignType().toUpperCase()).createSign(content, "|" + payConfigStorage.getSecretKey(), characterEncoding);
    }

    /**
    public boolean verifySource(String orderId) {
        LinkedHashMap<String, Object> params = new LinkedHashMap<String, Object>(3);
        params.put("mchnt_cd", payConfigStorage.getPid());
        params.put("order_id", orderId);
     */
    @Override
    public Map<String, Object> getParameter2Map(Map<String, String[]> parameterMap, InputStream is) {
        return null;
    }

    /**
     *
     * @param order 支付订单
     * @return 返回支付请求参数集合
     */
    private Map<String, Object> getOrderInfo(PayOrder order) {

        LinkedHashMap<String, Object> parameters = new LinkedHashMap<String, Object>();
        //商户代码
        parameters.put("mchnt_cd", payConfigStorage.getPid());
        //商户订单号
        parameters.put("order_id", order.getOutTradeNo());
        //交易金额
        parameters.put("order_amt", Util.conversionCentAmount(order.getPrice()));
        //交易币种
//        parameters.put("cur_type", null == order.getCurType() ? FuiouCurType.CNY:order.getCurType());
     */
    @Override
    public PayOutMessage successPayOutMessage(PayMessage payMessage) {
        return PayOutMessage.JSON().content("success","成功").build();
    }

    /**
            parameters.put("order_valid_time", DateUtils.minutesRemaining(order.getExpirationTime()) + "m");
        }
        else {
            //超时时间 1m-15天，m：分钟、h：小时、d天、1c当天有效，
            parameters.put("order_valid_time", "30m");
        }
        //银行代码
        parameters.put("iss_ins_cd", order.getBankType());
        parameters.put("goods_name", order.getSubject());
        //商品展示网址 //非必填
        parameters.put("goods_display_url", "");
        //备注 //非必填
        parameters.put("rem", "");
        //版本号
        parameters.put("ver", "1.0.1");
        parameters.putAll(order.getAttrs());
        return preOrderHandler(parameters, order);
    }

    /**
     * 对内容进行加密
     *
     * @param content           需要加密的内容
     * @param characterEncoding 字符编码
     * @return 加密后的字符串
     */
    @Override
    public String createSign(String content, String characterEncoding) {
        return SignUtils.valueOf(payConfigStorage.getSignType().toUpperCase()).createSign(content, "|" + payConfigStorage.getKeyPrivate(), characterEncoding);
    }


    /**
     * 将请求参数或者请求流转化为 Map
     *
     * @param request 通知请求
     * @return 获得回调的请求参数
     */
    @Override
    public NoticeParams getNoticeParams(NoticeRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String, Object> params = conversion(parameterMap, new LinkedHashMap<String, Object>(), "mchnt_cd");
        conversion(parameterMap, params, "order_id");
        conversion(parameterMap, params, "order_date");
        conversion(parameterMap, params, "order_amt");
        conversion(parameterMap, params, "order_st");
        conversion(parameterMap, params, "order_pay_code");
        conversion(parameterMap, params, "order_pay_error");
        conversion(parameterMap, params, "resv1");
        conversion(parameterMap, params, "fy_ssn");
        conversion(parameterMap, params, "md5");
        return new NoticeParams(params);
    }

    /**
     * 将parameterMap对应的key存放至params
     *
     * @param parameterMap 请求参数
     * @param params       转化的对象
     * @param key          需要取值的key
     * @return params
     */
    public Map<String, Object> conversion(Map<String, String[]> parameterMap, Map<String, Object> params, String key) {
        String[] values = parameterMap.get(key);
        String valueStr = "";
        for (int i = 0, len = values.length; i < len; i++) {
            valueStr += (i == len - 1) ? values[i] : values[i] + ",";
        }
        params.put(key, valueStr);
        return params;
    }

    /**
     * 获取输出消息，用户返回给支付端
     *
     * @param code    返回代码
     * @param message 返回信息
     * @return 消息实体
     */

    @Override
    public PayOutMessage getPayOutMessage(String code, String message) {
        return PayOutMessage.TEXT().content(code.toLowerCase()).build();
    }

    /**
     * 获取成功输出消息，用户返回给支付端
     * 主要用于拦截器中返回
     *
     * @param payMessage 支付回调消息
     * @return 返回输出消息
     */
    @Override
    public PayOutMessage successPayOutMessage(PayMessage payMessage) {
        return PayOutMessage.TEXT().content("success").build();
    }

    /**
     * 发送支付请求（form表单）
     *
     * @param orderInfo 发起支付的订单信息
     * @param method    请求方式  "post" "get",
     * @return form表单提交的html字符串
     */

    @Override
    public String buildRequest(Map<String, Object> orderInfo, MethodType method) {
        return getFormString(orderInfo, method, getReqUrl() + URL_FuiouSmpGate);
    }

    /**
     * 获取输出二维码，用户返回给支付端,
     * 暂未实现或无此功能
     *
     * @param order 发起支付的订单信息
     * @return 空
     */
    @Override
    public String getQrPay(PayOrder order) {
        throw new UnsupportedOperationException();
    }

    /**
     * 暂未实现或无此功能
     *
     * @param order 发起支付的订单信息
     * @return 不支持的操作异常
     */
    @Override
    public Map<String, Object> microPay(PayOrder order) {
        throw new UnsupportedOperationException();
    }

    /**
     * 根据参数形成form表单
     *
     * @param param  参数
     * @param method 请求方式 get_post
     * @param url    支付请求url地址
     * @return form表单html代码
     */
    private String getFormString(Map<String, Object> param, MethodType method, String url) {
        StringBuffer formHtml = new StringBuffer();
        formHtml.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">");
        formHtml.append("<title>提交到富友交易系统</title></head>");
        formHtml.append("<script type=\"text/javascript\">function submitForm()");
        formHtml.append("{document.getElementById(\"form\").submit();} </script>");
        formHtml.append("<body onload=\"javascript:submitForm();\">");
        formHtml.append("<form name=\"pay\" method=\"" + method.name().toLowerCase() + "\" ");
        formHtml.append("action=\"" + url + "\" id = \"form\">");

        for (Map.Entry entry : param.entrySet()) {
            Object o = entry.getValue();
            formHtml.append("<input type=\"hidden\" value = '" + o + "' name=\"" + entry.getKey() + "\"/>");
        }

        formHtml.append("</form></body></html>");

        return formHtml.toString();
    }

    /**
     * 交易查询接口
     *
     * @param tradeNo    支付平台订单号
     * @param outTradeNo 商户单号
     * @return 空
     */
    @Override
    public Map<String, Object> query(String tradeNo, String outTradeNo) {

        return query(new AssistOrder(tradeNo, outTradeNo));
    }

    /**
     * 交易查询接口
     *
     * @param assistOrder 查询条件
     * @return 返回查询回来的结果集，支付方原值返回
     */
    @Override
    public Map<String, Object> query(AssistOrder assistOrder) {

        LinkedHashMap<String, Object> params = new LinkedHashMap<>();
        params.put("mchnt_cd", payConfigStorage.getPid());
        params.put("order_id", assistOrder.getOutTradeNo());
        params.put("md5", createSign(SignTextUtils.parameters2Md5Str(params, "|"), payConfigStorage.getInputCharset()));
        return getHttpRequestTemplate().postForObject(getReqUrl() + URL_FuiouSmpAQueryGate + "?" + UriVariables.getMapToParameters(params), null, JSONObject.class);
    }


    /**
     * 交易关闭接口
     *
     * @param tradeNo    支付平台订单号
     * @param outTradeNo 商户单号
     * @return 空
     */
    @Override
    public Map<String, Object> close(String tradeNo, String outTradeNo) {
        throw new UnsupportedOperationException("不支持该操作");
    }

    /**
     * 交易关闭接口
     *
     * @param assistOrder 关闭订单
     * @return 返回支付方交易关闭后的结果
     */
    @Override
    public Map<String, Object> close(AssistOrder assistOrder) {
        throw new UnsupportedOperationException("不支持该操作");
    }

    /**
     * 申请退款接口
     *
     * @param refundOrder 退款订单信息
     * @return 退款返回结果集
     */
    @Override
    public RefundResult refund(RefundOrder refundOrder) {
        Map<String, Object> params = new HashMap<>();
        //商户代码
        params.put("mchnt_cd", payConfigStorage.getPid());
        //原交易日期
        params.put("origin_order_date", refundOrder.getOrderDate());
        //原订单号
        params.put("origin_order_id", refundOrder.getTradeNo());
        //退款金额
        params.put("refund_amt", Util.conversionCentAmount(refundOrder.getRefundAmount()));
        //备注
        params.put("rem", "");
        params.putAll(refundOrder.getAttrs());
        params.put("md5", createSign(SignTextUtils.parameters2Md5Str(params, "|"), payConfigStorage.getInputCharset()));
        JSONObject resultJson = getHttpRequestTemplate().postForObject(getReqUrl() + URL_FuiouSmpRefundGate, params, JSONObject.class);
        return FuiouRefundResult.create(resultJson);
    }


    /**
     * 查询退款
     *
     * @param refundOrder 退款订单单号信息
     * @return 返回支付方查询退款后的结果
     */
    @Override
    public Map<String, Object> refundquery(RefundOrder refundOrder) {
        return Collections.emptyMap();
    }


    /**
     * 下载对账单
     *
     * @param billDate 账单时间：日账单格式为yyyy-MM-dd，月账单格式为yyyy-MM。
     * @param billType 账单类型，商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型：trade、signcustomer；trade指商户基于支付宝交易收单的业务账单；signcustomer是指基于商户支付宝余额收入及支出等资金变动的帐务账单；
     * @return 空
     */
    @Override
    public Map<String, Object> downloadBill(Date billDate, BillType billType) {
        return Collections.emptyMap();
    }


}

<MSG> 富友增加，回调参数获取，configStorage增加privateKey取值设置

<DFF> @@ -1,5 +1,4 @@
 package com.egzosn.pay.fuiou.api;
-import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.egzosn.pay.common.api.BasePayService;
 import com.egzosn.pay.common.api.Callback;
@@ -7,6 +6,7 @@ import com.egzosn.pay.common.api.PayConfigStorage;
 import com.egzosn.pay.common.bean.*;
 import com.egzosn.pay.common.exception.PayErrorException;
 import com.egzosn.pay.common.http.HttpConfigStorage;
+import com.egzosn.pay.common.http.UriVariables;
 import com.egzosn.pay.common.util.sign.SignUtils;
 import com.egzosn.pay.common.util.str.StringUtils;
 import org.apache.commons.logging.Log;
@@ -101,8 +101,6 @@ public class FuiouPayService extends BasePayService {
     @Override
     public boolean signVerify(Map<String, Object> params, String responseSign) {
 
-        params = new LinkedHashMap<>(params);
-
         String sign = createSign(SignUtils.parameters2MD5Str(params, "|"), payConfigStorage.getInputCharset());
 
         return responseSign.equals(sign);
@@ -120,10 +118,14 @@ public class FuiouPayService extends BasePayService {
         params.put("mchnt_cd", payConfigStorage.getPid());
         params.put("order_id", order_id);
         params.put("md5", createSign(SignUtils.parameters2MD5Str(params, "|"), payConfigStorage.getInputCharset()));
-        JSONObject resultJson = getHttpRequestTemplate().postForObject(getReqUrl() + URL_FuiouSmpAQueryGate, params, JSONObject.class);
-        return "0000".equals(resultJson.getString("order_pay_code"));
+        JSONObject resultJson = getHttpRequestTemplate().postForObject(getReqUrl() + URL_FuiouSmpAQueryGate + "?" + UriVariables.getMapToParameters(params), null, JSONObject.class);
+        if (null == resultJson){
+            return false;
+        }
+        return "0000".equals(resultJson.getJSONObject("plain").getString("order_pay_code"));
     }
 
+
     /**
      * 将支付请求参数加密成md5
      * @param order 支付订单
@@ -168,7 +170,7 @@ public class FuiouPayService extends BasePayService {
      */
     @Override
     public String createSign(String content, String characterEncoding) {
-        return SignUtils.valueOf(payConfigStorage.getSignType().toUpperCase()).createSign(content, "|" + payConfigStorage.getSecretKey(), characterEncoding);
+        return SignUtils.valueOf(payConfigStorage.getSignType().toUpperCase()).createSign(content, "|" + payConfigStorage.getKeyPrivate(), characterEncoding);
     }
 
     /**
@@ -179,7 +181,34 @@ public class FuiouPayService extends BasePayService {
      */
     @Override
     public Map<String, Object> getParameter2Map(Map<String, String[]> parameterMap, InputStream is) {
-        return null;
+        Map<String, Object> params  = conversion(parameterMap,  new LinkedHashMap<String, Object>(), "mchnt_cd");
+        conversion(parameterMap,  params, "order_id");
+        conversion(parameterMap,  params, "order_date");
+        conversion(parameterMap,  params, "order_amt");
+        conversion(parameterMap,  params, "order_st");
+        conversion(parameterMap,  params, "order_pay_code");
+        conversion(parameterMap,  params, "order_pay_error");
+        conversion(parameterMap,  params, "resv1");
+        conversion(parameterMap,  params, "fy_ssn");
+        conversion(parameterMap,  params, "md5");
+        return params;
+    }
+
+    /**
+     *  将parameterMap对应的key存放至params
+     * @param parameterMap 请求参数
+     * @param params 转化的对象
+     * @param key 需要取值的key
+     * @return params
+     */
+    public Map<String, Object> conversion(Map<String, String[]> parameterMap,  Map<String, Object> params ,String key){
+        String[] values = parameterMap.get(key);
+        String valueStr = "";
+        for (int i = 0,len =  values.length; i < len; i++) {
+            valueStr += (i == len - 1) ?  values[i] : values[i] + ",";
+        }
+        params.put(key, valueStr);
+        return params;
     }
 
     /**
@@ -201,7 +230,7 @@ public class FuiouPayService extends BasePayService {
      */
     @Override
     public PayOutMessage successPayOutMessage(PayMessage payMessage) {
-        return PayOutMessage.JSON().content("success","成功").build();
+        return PayOutMessage.TEXT().content("success").build();
     }
 
     /**

富友增加，回调参数获取，configStorage增加privateKey取值设置