mirror of
https://gitee.com/egzosn/pay-java-parent.git
synced 2026-05-18 04:27:38 +08:00
包名修改
This commit is contained in:
19
pay-java-fuiou/src/main/java/com/egzosn/pay/fuiou/Test.java
Normal file
19
pay-java-fuiou/src/main/java/com/egzosn/pay/fuiou/Test.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.egzosn.pay.fuiou;/**
|
||||
* Created by Fuzx on 2017/2/10 0010.
|
||||
*/
|
||||
|
||||
import com.egzosn.pay.common.util.sign.SignUtils;
|
||||
|
||||
/**
|
||||
* @author Fuzx
|
||||
* @create 2017 2017/2/10 0010
|
||||
*/
|
||||
public class Test {
|
||||
public static void main(String[] args) {
|
||||
String content="0002230F0348879|17021013591343700615|805a9aphsvmbf6qih8k66vu1svafj99m";
|
||||
System.out.println(SignUtils.valueOf("MD5").createSign(content, "", "UTF-8"));
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.egzosn.pay.fuiou.api;/**
|
||||
* Created by Fuzx on 2017/1/16 0016.
|
||||
*/
|
||||
|
||||
import com.egzosn.pay.common.before.api.BasePayConfigStorage;
|
||||
|
||||
/**
|
||||
* @author Fuzx
|
||||
* @create 2017 2017/1/16 0016
|
||||
*/
|
||||
public class FuiouPayConfigStorage extends BasePayConfigStorage {
|
||||
|
||||
public String mchntCd;//商户代码
|
||||
public String mchntKey;//商户密钥
|
||||
|
||||
|
||||
@Override
|
||||
public String getAppid() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPartner() {
|
||||
return mchntCd;
|
||||
}
|
||||
|
||||
public void setPartner(String partner) {
|
||||
this.mchntCd = partner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSeller() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSecretKey() {
|
||||
return mchntKey;
|
||||
}
|
||||
|
||||
public void setSecretKey(String mchntKey){
|
||||
this.mchntKey = mchntKey;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
package com.egzosn.pay.fuiou.api;/**
|
||||
* Created by Fuzx on 2017/1/16 0016.
|
||||
*/
|
||||
|
||||
import com.egzosn.pay.common.before.api.BasePayService;
|
||||
import com.egzosn.pay.common.before.api.PayConfigStorage;
|
||||
import com.egzosn.pay.common.before.api.RequestExecutor;
|
||||
import com.egzosn.pay.common.bean.MethodType;
|
||||
import com.egzosn.pay.common.bean.PayOrder;
|
||||
import com.egzosn.pay.common.bean.PayOutMessage;
|
||||
import com.egzosn.pay.common.before.bean.result.PayError;
|
||||
import com.egzosn.pay.common.exception.PayErrorException;
|
||||
import com.egzosn.pay.common.util.sign.SignUtils;
|
||||
import com.egzosn.pay.common.util.str.StringUtils;
|
||||
import com.egzosn.pay.fuiou.utils.SimplePostRequestExecutor;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Fuzx
|
||||
* @create 2017 2017/1/16 0016
|
||||
*/
|
||||
public class FuiouPayService extends BasePayService {
|
||||
|
||||
protected final Log log = LogFactory.getLog(FuiouPayService.class);
|
||||
|
||||
public final static String fuiouBaseDomain = "https://pay.fuiou.com/";//正式域名
|
||||
// public final static String fuiouBaseDomain = "http://www-1.fuiou.com:8888/wg1_run/";//测试域名
|
||||
|
||||
public final static String fuiouSmpGate = fuiouBaseDomain + "smpGate.do";//B2C/B2B支付
|
||||
|
||||
public final static String fuiouNewSmpGate = fuiouBaseDomain + "newSmpGate.do";//B2C/B2B支付(跨境支付)
|
||||
public final static String fuiouSmpRefundGate = fuiouBaseDomain + "newSmpRefundGate.do";//订单退款
|
||||
|
||||
public final static String fuiouSmpQueryGate = fuiouBaseDomain + "smpQueryGate.do";//3.2 支付结果查询
|
||||
public final static String fuiouSmpAQueryGate = fuiouBaseDomain + "smpAQueryGate.do";//3.3 支付结果查询(直接返回)
|
||||
|
||||
public FuiouPayService(PayConfigStorage payConfigStorage) {
|
||||
setPayConfigStorage(payConfigStorage);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getHttpsVerifyUrl() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调校验
|
||||
* @param params 回调回来的参数集
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean verify(Map<String, String> params) {
|
||||
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 getSignVerify(params, params.get("md5")) && "0000".equals(verifyUrl(params.get("order_id")));//返回参数校验 和 重新请求订单检查数据是否合法
|
||||
} catch (PayErrorException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验回调参数是否合法
|
||||
* @param params 参数集
|
||||
* @param returnSign
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean getSignVerify(Map<String, String> params, String returnSign) {
|
||||
LinkedHashSet<String> keySet = new LinkedHashSet<>();
|
||||
keySet.add("mchnt_cd");//商户代码
|
||||
keySet.add("order_id");//商户订单号
|
||||
keySet.add("order_date");//订单日期
|
||||
keySet.add("order_amt");//交易金额
|
||||
keySet.add("order_st");//订单状态
|
||||
keySet.add("order_pay_code");//错误代码
|
||||
keySet.add("order_pay_error");//错误中文描述
|
||||
keySet.add("resv1");//保留字段
|
||||
keySet.add("fy_ssn");//富友流水号
|
||||
StringBuilder verifyMD5Str = new StringBuilder();
|
||||
for (String keyStr : keySet) {
|
||||
String keyValue = params.get(keyStr);
|
||||
if (null == keyValue){
|
||||
log.debug(String.format("富友支付返回结果校验:<参数:%s>不能为空,",keyStr));
|
||||
}
|
||||
verifyMD5Str.append(keyValue).append("|");
|
||||
}
|
||||
String sign = createSign(verifyMD5Str.deleteCharAt(verifyMD5Str.length() -1).toString(),payConfigStorage.getInputCharset());
|
||||
// System.out.println("加密串"+verifyMD5Str+",,返回参数生成MD5="+sign+",,返回MD5摘要值"+returnSign);
|
||||
if(returnSign.equals(sign)){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起请求校验订单是否支付成功
|
||||
* @param order_id
|
||||
* @return
|
||||
* @throws PayErrorException
|
||||
*/
|
||||
@Override
|
||||
public String verifyUrl(String order_id) throws PayErrorException {
|
||||
// LinkedHashMap param = new LinkedHashMap();
|
||||
// param.put("mchnt_cd",payConfigStorage.getPartner());
|
||||
// param.put("order_id",order_id);
|
||||
// param.put("md5",createSign(SignUtils.parameters2MD5Str(param,"|"),payConfigStorage.getInputCharset()));
|
||||
List<BasicNameValuePair> pairList = new ArrayList<BasicNameValuePair>();
|
||||
pairList.add(new BasicNameValuePair("mchnt_cd",payConfigStorage.getPartner()));
|
||||
pairList.add(new BasicNameValuePair("order_id",order_id));
|
||||
pairList.add(new BasicNameValuePair("md5",createSign(SignUtils.parameters2MD5Str(pairList,"|"),payConfigStorage.getInputCharset())));
|
||||
return execute(new SimplePostRequestExecutor(), fuiouSmpAQueryGate,pairList);
|
||||
// JSONObject jsonObject = XML.toJSONObject(responseContent);
|
||||
|
||||
// return getFormString(param,MethodType.POST,fuiouSmpAQueryGate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws PayErrorException {
|
||||
int retryTimes = 0;
|
||||
do {
|
||||
try {
|
||||
return executeInternal(executor, uri, data);
|
||||
} catch (PayErrorException e) {
|
||||
PayError error = (PayError) e.getPayError();
|
||||
if ("404".equals(error.getErrorCode()) ) {
|
||||
int sleepMillis = retrySleepMillis * (1 << retryTimes);
|
||||
try {
|
||||
log.debug(String.format("富友支付系统错误,错误信息:<%s>,(%s)ms 后重试(第%s次)",e.getMessage(),sleepMillis, retryTimes + 1));
|
||||
Thread.sleep(sleepMillis);
|
||||
} catch (InterruptedException e1) {
|
||||
throw new RuntimeException(e1);
|
||||
}
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} while (++retryTimes < maxRetryTimes);
|
||||
|
||||
throw new RuntimeException("富友支付服务端异常,超出重试次数");
|
||||
}
|
||||
|
||||
/**
|
||||
* 对支付请求参数进行加密,排序
|
||||
* @param order 支付订单
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> orderInfo(PayOrder order) {
|
||||
LinkedHashMap<String, Object> parameters = getOrderInfo(order);
|
||||
String sign = createSign(SignUtils.parameters2MD5Str(parameters, "|"), payConfigStorage.getInputCharset());
|
||||
parameters.put("md5", sign);
|
||||
return parameters;
|
||||
}
|
||||
|
||||
private LinkedHashMap<String, Object> getOrderInfo(PayOrder order) {
|
||||
LinkedHashMap<String, Object> parameters = new LinkedHashMap<String, Object>();
|
||||
parameters.put("mchnt_cd", payConfigStorage.getPartner());//商户代码
|
||||
parameters.put("order_id", order.getTradeNo());//商户订单号
|
||||
parameters.put("order_amt", order.getPrice());//交易金额
|
||||
// parameters.put("cur_type", null == order.getCurType() ? FuiouCurType.CNY:order.getCurType());//交易币种
|
||||
parameters.put("order_pay_type", order.getTransactionType());//支付类型
|
||||
parameters.put("page_notify_url", payConfigStorage.getReturnUrl());//商户接受支付结果通知地址
|
||||
parameters.put("back_notify_url", StringUtils.isBlank(payConfigStorage.getNotifyUrl()) ? "" : payConfigStorage.getNotifyUrl());//商户接受的支付结果后台通知地址 //非必填
|
||||
parameters.put("order_valid_time", "30m");//超时时间 1m-15天,m:分钟、h:小时、d天、1c当天有效,
|
||||
parameters.put("iss_ins_cd", order.getBankType());//银行代码
|
||||
parameters.put("goods_name", order.getSubject());
|
||||
parameters.put("goods_display_url", "1");//商品展示网址 //非必填
|
||||
parameters.put("rem", "1");//备注 //非必填
|
||||
parameters.put("ver", "1.0.1");//版本号
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对内容进行加密
|
||||
* @param content 需要签名的内容
|
||||
* @param characterEncoding 字符编码
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String createSign(String content, String characterEncoding) {
|
||||
return SignUtils.valueOf(payConfigStorage.getSignType().toUpperCase()).createSign(content, "|" + payConfigStorage.getSecretKey(), characterEncoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将参数拼凑成String
|
||||
* @param parameterMap 请求参数
|
||||
* @param is 请求流
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> getParameter2Map(Map<String, String[]> parameterMap, InputStream is) {
|
||||
Map<String, String> params = new TreeMap<String, String>();
|
||||
for (Iterator iter = parameterMap.keySet().iterator(); iter.hasNext(); ) {
|
||||
String name = (String) iter.next();
|
||||
String[] values = parameterMap.get(name);
|
||||
String valueStr = "";
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
valueStr = (i == values.length - 1) ? valueStr + values[i]
|
||||
: valueStr + values[i] + ",";
|
||||
}
|
||||
//乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
|
||||
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
|
||||
params.put(name, valueStr);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayOutMessage getPayOutMessage(String code, String message) {
|
||||
return PayOutMessage.TEXT().content(code.toLowerCase()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildRequest(Map<String, Object> orderInfo, MethodType method) {
|
||||
return getFormString(orderInfo, method,fuiouSmpGate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据参数行程form表单
|
||||
* @param param 参数
|
||||
* @param method 请求方式 get_post
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
private String getFormString(Map<String, Object> param, MethodType method,String url) {
|
||||
StringBuffer formHtml = new StringBuffer();
|
||||
|
||||
formHtml.append("<form id=\"fuiousubmit\" name=\"fuiousubmit\" action=\"")
|
||||
.append(url)
|
||||
.append("\" accept-charset=\"UTF-8\" onsubmit=\"document.charset='UTF-8';")
|
||||
// .append( payConfigStorage.getInputCharset())
|
||||
.append("\" method=\"")
|
||||
.append(method.name().toLowerCase()).append("\">");
|
||||
|
||||
for (String key : param.keySet()) {
|
||||
Object o = param.get(key);
|
||||
if (null == o || "null".equals(o) || "".equals(o)) {
|
||||
continue;
|
||||
}
|
||||
formHtml.append("<input type=\"hidden\" name=\"" + key + "\" value=\"" + param.get(key) + "\"/>");
|
||||
}
|
||||
|
||||
|
||||
//submit按钮控件请不要含有name属性
|
||||
// formHtml.append("<input type=\"submit\" value=\"\" style=\"display:none;\">");
|
||||
formHtml.append("</form>");
|
||||
formHtml.append("<script>document.forms['fuiousubmit'].submit();</script>");
|
||||
|
||||
return formHtml.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成二维码支付
|
||||
* 暂未实现或无此功能
|
||||
*
|
||||
* @param orderInfo 发起支付的订单信息
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public BufferedImage genQrPay(Map<String, Object> orderInfo) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> query(String tradeNo, String outTradeNo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> close(String tradeNo, String outTradeNo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> refund(String tradeNo, String outTradeNo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> refundquery(String tradeNo, String outTradeNo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object downloadbill(Date billDate, String billType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.egzosn.pay.fuiou.bean;/**
|
||||
* Created by Fuzx on 2017/1/24 0024.
|
||||
*/
|
||||
|
||||
import com.egzosn.pay.common.bean.CurType;
|
||||
|
||||
/**
|
||||
* @author Fuzx
|
||||
* @create 2017 2017/1/24 0024
|
||||
*/
|
||||
public enum FuiouCurType implements CurType {
|
||||
|
||||
CNY("人民币"),
|
||||
USD("美元"),
|
||||
HKD("港币"),
|
||||
MOP("澳门元"),
|
||||
EUR("欧元"),
|
||||
TWD("新台币"),
|
||||
KRW("韩元"),
|
||||
JPY("日元"),
|
||||
SGD("新加坡元"),
|
||||
AUD("澳大利亚元");
|
||||
|
||||
private String name;
|
||||
private int index;
|
||||
|
||||
private FuiouCurType(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
@Override
|
||||
public String getCurType(){
|
||||
return this.name();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.egzosn.pay.fuiou.bean;
|
||||
|
||||
import com.egzosn.pay.common.bean.TransactionType;
|
||||
|
||||
/**
|
||||
* 微信交易类型
|
||||
* @author egan
|
||||
* @email egzosn@gmail.com
|
||||
* @date 2016/10/19 22:58
|
||||
*/
|
||||
public enum FuiouTransactionType implements TransactionType {
|
||||
B2B(""),
|
||||
B2C("")
|
||||
;
|
||||
|
||||
private String method;
|
||||
|
||||
private FuiouTransactionType(String method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return this.name();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取接口名称
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return this.method;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.egzosn.pay.fuiou.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.egzosn.pay.common.before.api.RequestExecutor;
|
||||
import com.egzosn.pay.common.before.bean.result.PayError;
|
||||
import com.egzosn.pay.common.exception.PayErrorException;
|
||||
import com.egzosn.pay.common.util.XML;
|
||||
import com.egzosn.pay.common.before.util.http.Utf8ResponseHandler;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author egan
|
||||
* @email egzosn@gmail.com
|
||||
* @date 2016-5-18 14:09:01
|
||||
*/
|
||||
public class SimplePostRequestExecutor implements RequestExecutor<String, Object> {
|
||||
|
||||
@Override
|
||||
public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, Object postEntity) throws PayErrorException, ClientProtocolException, IOException {
|
||||
HttpPost httpPost = new HttpPost(uri);
|
||||
// httpPost.setHeader("Content-Type","application/x-www-from-urlencoded");
|
||||
if (httpProxy != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
|
||||
httpPost.setConfig(config);
|
||||
}
|
||||
if (postEntity instanceof Map) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Map pe = (Map) postEntity;
|
||||
for (Object key : pe.keySet()) {
|
||||
builder.append(key).append("=").append(pe.get(key)).append("&");
|
||||
}
|
||||
if (builder.length() > 1) {
|
||||
builder.deleteCharAt(builder.length() - 1);
|
||||
}
|
||||
StringEntity entity = new StringEntity(builder.toString(), Consts.UTF_8);
|
||||
// entity.setContentType("application/x-www-from-urlencoded");
|
||||
httpPost.setEntity(entity);
|
||||
} else if (postEntity instanceof String) {
|
||||
|
||||
StringEntity entity = new StringEntity((String) postEntity, Consts.UTF_8);
|
||||
httpPost.setEntity(entity);
|
||||
}else if(postEntity instanceof List){
|
||||
//表单方式
|
||||
httpPost.setEntity(new UrlEncodedFormEntity((List<BasicNameValuePair>)postEntity, Consts.UTF_8));
|
||||
}
|
||||
|
||||
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
|
||||
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
|
||||
// System.out.println("直接返回的查询结果-->"+responseContent);
|
||||
// responseContent = responseContent.replace("<ap>","").replace("</ap>","").replace("<plain>","").replace("</plain>","");
|
||||
JSONObject jsonObject = XML.toJSONObject(responseContent);//包含md5
|
||||
JSONObject plain = XML.toJSONObject("<a>"+jsonObject.getString("plain")+"</a>");//"plain" -> "<order_pay_code>5002</order_pay_code><order_pay_error>验证签名失败</order_pay_error><order_id></order_id><order_st></order_st><fy_ssn></fy_ssn><resv1></resv1>"
|
||||
|
||||
if("0000".equals(plain.getString("order_pay_code"))){
|
||||
return "0000";
|
||||
}else{
|
||||
throw new PayErrorException(new PayError(404,plain.getString("order_pay_error"),responseContent));
|
||||
}
|
||||
}finally {
|
||||
httpPost.releaseConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user