mirror of
https://gitee.com/egzosn/pay-java-parent.git
synced 2026-05-13 17:30:18 +08:00
Merge branch 'develop' of https://git.oschina.net/egzosn/pay-java-parent into develop-Actinia
# Conflicts: # README.md # pay-java-union/src/main/java/com/egzosn/pay/union/api/UnionPayConfigStorage.java
This commit is contained in:
@@ -16,22 +16,35 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
public abstract class BasePayConfigStorage implements PayConfigStorage{
|
||||
|
||||
|
||||
// ali rsa_private 商户私钥,pkcs8格式
|
||||
//wx api_key 应用私钥(生成签名时使用)
|
||||
private volatile String keyPrivate ;
|
||||
// 支付平台公钥(签名校验使用)
|
||||
/**
|
||||
* 应用私钥,rsa_private pkcs8格式 生成签名时使用
|
||||
*/
|
||||
private volatile String keyPrivate;
|
||||
/**
|
||||
* 支付平台公钥(签名校验使用)
|
||||
*/
|
||||
private volatile String keyPublic;
|
||||
//异步回调地址
|
||||
/**
|
||||
* 异步回调地址
|
||||
*/
|
||||
private volatile String notifyUrl;
|
||||
//同步回调地址
|
||||
private volatile String returnUrl;;
|
||||
//签名加密类型
|
||||
/**
|
||||
* 同步回调地址,支付完成后展示的页面
|
||||
*/
|
||||
private volatile String returnUrl;
|
||||
/**
|
||||
* 签名加密类型
|
||||
*/
|
||||
private volatile String signType;
|
||||
//字符类型
|
||||
/**
|
||||
* 字符类型
|
||||
*/
|
||||
private volatile String inputCharset;
|
||||
|
||||
|
||||
//支付类型 aliPay 支付宝, wxPay微信..等等,开发者自定义,唯一
|
||||
/**
|
||||
* 支付类型 aliPay 支付宝, wxPay微信..等等,扩展支付模块定义唯一。
|
||||
*/
|
||||
private volatile String payType;
|
||||
|
||||
/**
|
||||
@@ -40,13 +53,21 @@ public abstract class BasePayConfigStorage implements PayConfigStorage{
|
||||
private volatile MsgType msgType;
|
||||
|
||||
|
||||
// 访问令牌 每次请求其他方法都要传入的值
|
||||
/**
|
||||
* 访问令牌 每次请求其他方法都要传入的值
|
||||
*/
|
||||
private volatile String accessToken;
|
||||
// access token 到期时间时间戳
|
||||
/**
|
||||
* access token 到期时间时间戳
|
||||
*/
|
||||
private volatile long expiresTime;
|
||||
//授权码锁
|
||||
/**
|
||||
* 授权码锁
|
||||
*/
|
||||
private Lock accessTokenLock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* 是否为沙箱环境,默认为正式环境
|
||||
*/
|
||||
private boolean isTest = false;
|
||||
|
||||
|
||||
@@ -77,6 +98,7 @@ public abstract class BasePayConfigStorage implements PayConfigStorage{
|
||||
this.notifyUrl = notifyUrl;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getReturnUrl() {
|
||||
return returnUrl;
|
||||
|
||||
@@ -14,21 +14,14 @@ import java.util.concurrent.locks.Lock;
|
||||
*/
|
||||
public interface PayConfigStorage {
|
||||
|
||||
/*
|
||||
/**
|
||||
* 应用id
|
||||
* @return 应用id
|
||||
*/
|
||||
String getAppid();
|
||||
|
||||
/**
|
||||
* 合作商唯一标识
|
||||
* @see #getPid() 代替者
|
||||
* @return 合作商唯一标识
|
||||
*/
|
||||
@Deprecated
|
||||
String getPartner();
|
||||
/**
|
||||
* 合作商唯一标识
|
||||
* @see #getPartner() 代替者
|
||||
* @return 合作商唯一标识
|
||||
*/
|
||||
String getPid();
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.egzosn.pay.common.api;
|
||||
|
||||
import com.egzosn.pay.common.bean.PayMessage;
|
||||
import com.egzosn.pay.common.bean.PayOutMessage;
|
||||
|
||||
import com.egzosn.pay.common.util.LogExceptionHandler;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -43,18 +44,32 @@ import java.util.concurrent.Future;
|
||||
*/
|
||||
public class PayMessageRouter {
|
||||
|
||||
protected final Log log = LogFactory.getLog(PayMessageRouter.class);
|
||||
|
||||
protected final Log LOG = LogFactory.getLog(PayMessageRouter.class);
|
||||
/**
|
||||
* 异步线程大小
|
||||
*/
|
||||
private static final int DEFAULT_THREAD_POOL_SIZE = 100;
|
||||
|
||||
/**
|
||||
* 规则集
|
||||
*/
|
||||
private final List<PayMessageRouterRule> rules = new ArrayList<PayMessageRouterRule>();
|
||||
|
||||
/**
|
||||
* 支付服务
|
||||
*/
|
||||
private final PayService payService;
|
||||
|
||||
/**
|
||||
* 异步线程处理器
|
||||
*/
|
||||
private ExecutorService executorService;
|
||||
|
||||
/**
|
||||
* 支付异常处理器
|
||||
*/
|
||||
private PayErrorExceptionHandler exceptionHandler;
|
||||
|
||||
/**
|
||||
* 根据支付服务创建路由
|
||||
* @param payService 支付服务
|
||||
*/
|
||||
public PayMessageRouter(PayService payService) {
|
||||
this.payService = payService;
|
||||
this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE);
|
||||
@@ -130,6 +145,7 @@ public class PayMessageRouter {
|
||||
if(rule.isAsync()) {
|
||||
futures.add(
|
||||
executorService.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
rule.service(payMessage, payService, exceptionHandler);
|
||||
}
|
||||
@@ -138,7 +154,7 @@ public class PayMessageRouter {
|
||||
} else {
|
||||
res = rule.service(payMessage, payService, exceptionHandler);
|
||||
// 在同步操作结束,session访问结束
|
||||
log.debug("End session access: async=false, fromPay=" + payMessage.getFromPay());
|
||||
LOG.debug("End session access: async=false, fromPay=" + payMessage.getFromPay());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,12 +165,12 @@ public class PayMessageRouter {
|
||||
for (Future future : futures) {
|
||||
try {
|
||||
future.get();
|
||||
log.debug("End session access: async=true, fromPay=" + payMessage.getFromPay());
|
||||
LOG.debug("End session access: async=true, fromPay=" + payMessage.getFromPay());
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
log.error("Error happened when wait task finish", e);
|
||||
LOG.error("Error happened when wait task finish", e);
|
||||
} catch (ExecutionException e) {
|
||||
log.error("Error happened when wait task finish", e);
|
||||
LOG.error("Error happened when wait task finish", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,25 +27,39 @@ public class PayMessageRouterRule {
|
||||
|
||||
|
||||
private final PayMessageRouter routerBuilder;
|
||||
/**
|
||||
* 默认同步
|
||||
*/
|
||||
private boolean async = false;
|
||||
|
||||
private boolean async = true;
|
||||
|
||||
private String fromPay;
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
*/
|
||||
private String msgType;
|
||||
|
||||
/**
|
||||
* 支付类型
|
||||
*/
|
||||
private String payType;
|
||||
|
||||
/**
|
||||
* 交易类型
|
||||
*/
|
||||
private String[] transactionType;
|
||||
|
||||
private String discount;
|
||||
|
||||
private String rDiscount;
|
||||
|
||||
/**
|
||||
* 简介
|
||||
*/
|
||||
private String subject;
|
||||
|
||||
/**
|
||||
* 正则匹配
|
||||
*/
|
||||
private String rSubject;
|
||||
|
||||
/**
|
||||
* 匹配的键名称
|
||||
*/
|
||||
private String key;
|
||||
/**
|
||||
* 匹配的键名称对应的值 正则
|
||||
*/
|
||||
private String rValue;
|
||||
|
||||
private boolean reEnter = false;
|
||||
|
||||
@@ -101,27 +115,7 @@ public class PayMessageRouterRule {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果discount等于某值
|
||||
*
|
||||
* @param discount discount等于某值
|
||||
* @return Route规则
|
||||
*/
|
||||
public PayMessageRouterRule discount(String discount) {
|
||||
this.discount = discount;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果discount匹配该正则表达式
|
||||
*
|
||||
* @param regex discount匹配该正则表达式
|
||||
* @return Route规则
|
||||
*/
|
||||
public PayMessageRouterRule rDiscount(String regex) {
|
||||
this.rDiscount = regex;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果subject等于某值
|
||||
@@ -144,6 +138,18 @@ public class PayMessageRouterRule {
|
||||
this.rSubject = regex;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* 如果subject匹配该正则表达式
|
||||
*
|
||||
* @param key 需要匹配支付消息内键的名字
|
||||
* @param regex key值对应的正则
|
||||
* @return Route规则
|
||||
*/
|
||||
public PayMessageRouterRule key2RValue(String key, String regex) {
|
||||
this.key = key;
|
||||
this.rValue = regex;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -228,19 +234,14 @@ public class PayMessageRouterRule {
|
||||
*/
|
||||
protected boolean test(PayMessage payMessage) {
|
||||
return (
|
||||
(this.fromPay == null || this.fromPay.toLowerCase().equals((payMessage.getFromPay() ==null?null:payMessage.getFromPay().toLowerCase())))
|
||||
&&
|
||||
(this.msgType == null || this.msgType.toLowerCase().equals((payMessage.getMsgType() ==null?null:payMessage.getMsgType().toLowerCase())))
|
||||
(this.msgType == null || this.msgType.toLowerCase().equals((payMessage.getMsgType() ==null?null:payMessage.getMsgType().toLowerCase())))
|
||||
&&
|
||||
(this.payType == null || this.payType.equals((payMessage.getPayType() == null ? null : payMessage.getPayType())))
|
||||
&&
|
||||
(this.transactionType == null || equalsTransactionType(payMessage.getTransactionType()))
|
||||
&&
|
||||
(this.discount == null || this.discount
|
||||
.equals(payMessage.getDiscount() == null ? null : payMessage.getDiscount().trim()))
|
||||
&&
|
||||
(this.rDiscount == null || Pattern
|
||||
.matches(this.rDiscount, payMessage.getDiscount() == null ? "" : payMessage.getDiscount().trim()))
|
||||
(this.key == null ||this.rValue == null || Pattern
|
||||
.matches(this.rValue, payMessage.getPayMessage().get(key) == null ? "" : payMessage.getPayMessage().get(key).toString().trim()))
|
||||
&&
|
||||
(this.subject == null || this.subject
|
||||
.equals(payMessage.getSubject() == null ? null : payMessage.getSubject().trim()))
|
||||
@@ -319,13 +320,6 @@ public class PayMessageRouterRule {
|
||||
this.async = async;
|
||||
}
|
||||
|
||||
public String getFromPay() {
|
||||
return fromPay;
|
||||
}
|
||||
|
||||
public void setFromPay(String fromPay) {
|
||||
this.fromPay = fromPay;
|
||||
}
|
||||
|
||||
public String getMsgType() {
|
||||
return msgType;
|
||||
@@ -351,20 +345,20 @@ public class PayMessageRouterRule {
|
||||
this.transactionType = transactionType;
|
||||
}
|
||||
|
||||
public String getDiscount() {
|
||||
return discount;
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setDiscount(String discount) {
|
||||
this.discount = discount;
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getrDiscount() {
|
||||
return rDiscount;
|
||||
public String getrValue() {
|
||||
return rValue;
|
||||
}
|
||||
|
||||
public void setrDiscount(String rDiscount) {
|
||||
this.rDiscount = rDiscount;
|
||||
public void setrValue(String rValue) {
|
||||
this.rValue = rValue;
|
||||
}
|
||||
|
||||
public String getSubject() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original huodull or egan.
|
||||
* Copyright 2002-2017 the original egan.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,6 +23,7 @@ package com.egzosn.pay.common.bean;
|
||||
* email egzosn@gmail.com
|
||||
* date 2017/2/7 9:52
|
||||
* </pre>
|
||||
* 请求方式
|
||||
*/
|
||||
public enum MethodType {
|
||||
GET, POST
|
||||
|
||||
@@ -22,11 +22,17 @@ public class PayOrder {
|
||||
private String outTradeNo;
|
||||
//银行卡类型
|
||||
private String bankType;
|
||||
//设备号
|
||||
//设备信息,
|
||||
private String deviceInfo;
|
||||
//支付创建ip
|
||||
private String spbillCreateIp;
|
||||
//付款条码串 与设备号类似???
|
||||
private String authCode;
|
||||
//
|
||||
//WAP支付链接
|
||||
private String wapUrl;
|
||||
//WAP支付网页名称
|
||||
private String wapName;
|
||||
//微信会员唯一标识
|
||||
private String openid;
|
||||
//交易类型
|
||||
private TransactionType transactionType;
|
||||
@@ -119,6 +125,14 @@ public class PayOrder {
|
||||
this.bankType = bankType;
|
||||
}
|
||||
|
||||
public String getSpbillCreateIp() {
|
||||
return spbillCreateIp;
|
||||
}
|
||||
|
||||
public void setSpbillCreateIp(String spbillCreateIp) {
|
||||
this.spbillCreateIp = spbillCreateIp;
|
||||
}
|
||||
|
||||
public String getAuthCode() {
|
||||
return authCode;
|
||||
}
|
||||
@@ -153,6 +167,22 @@ public class PayOrder {
|
||||
this.outTradeNo = outTradeNo;
|
||||
}
|
||||
|
||||
public String getWapUrl() {
|
||||
return wapUrl;
|
||||
}
|
||||
|
||||
public void setWapUrl(String wapUrl) {
|
||||
this.wapUrl = wapUrl;
|
||||
}
|
||||
|
||||
public String getWapName() {
|
||||
return wapName;
|
||||
}
|
||||
|
||||
public void setWapName(String wapName) {
|
||||
this.wapName = wapName;
|
||||
}
|
||||
|
||||
public String getOpenid() {
|
||||
return openid;
|
||||
}
|
||||
|
||||
@@ -32,9 +32,13 @@ import static com.egzosn.pay.common.http.UriVariables.getMapToParameters;
|
||||
* </pre>
|
||||
*/
|
||||
public class ClientHttpRequest<T> extends HttpEntityEnclosingRequestBase implements org.apache.http.client.ResponseHandler<T>{
|
||||
//http请求
|
||||
/**
|
||||
* http请求方式 get pos
|
||||
*/
|
||||
private MethodType method;
|
||||
//响应类型
|
||||
/**
|
||||
* 响应类型
|
||||
*/
|
||||
private Class<T> responseType;
|
||||
|
||||
|
||||
@@ -43,40 +47,80 @@ public class ClientHttpRequest<T> extends HttpEntityEnclosingRequestBase impleme
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 空构造
|
||||
*/
|
||||
public ClientHttpRequest() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据请求地址 请求方法,请求内容对象
|
||||
* @param uri 请求地址
|
||||
* @param method 请求方法
|
||||
* @param request 请求内容
|
||||
*/
|
||||
public ClientHttpRequest(URI uri, MethodType method, Object request) {
|
||||
this.setURI(uri);
|
||||
this.method = method;
|
||||
this(uri, method);
|
||||
setParameters(request);
|
||||
}
|
||||
/**
|
||||
* 根据请求地址 请求方法
|
||||
* @param uri 请求地址
|
||||
* @param method 请求方法
|
||||
*/
|
||||
public ClientHttpRequest(URI uri, MethodType method) {
|
||||
this.setURI(uri);
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据请求地址
|
||||
* @param uri 请求地址
|
||||
*/
|
||||
public ClientHttpRequest(URI uri) {
|
||||
this.setURI(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据请求地址
|
||||
* @param uri 请求地址
|
||||
*/
|
||||
public ClientHttpRequest(String uri) {
|
||||
this.setURI(URI.create(uri));
|
||||
}
|
||||
/**
|
||||
* 根据请求地址 请求方法
|
||||
* @param uri 请求地址
|
||||
* @param method 请求方法
|
||||
*/
|
||||
public ClientHttpRequest(String uri, MethodType method) {
|
||||
this.setURI(URI.create(uri));
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据请求地址 请求方法,请求内容对象
|
||||
* @param uri 请求地址
|
||||
* @param method 请求方法
|
||||
* @param request 请求内容
|
||||
*/
|
||||
public ClientHttpRequest(String uri, MethodType method, Object request) {
|
||||
this.setURI(URI.create(uri));
|
||||
this.method = method;
|
||||
this(uri, method);
|
||||
setParameters(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置请求方式
|
||||
*
|
||||
* @param method 请求方式
|
||||
* {@link com.egzosn.pay.common.bean.MethodType} 请求方式
|
||||
*/
|
||||
public void setMethod(MethodType method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求方式
|
||||
* @return 请求方式
|
||||
*/
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return method.name();
|
||||
@@ -153,11 +197,11 @@ public class ClientHttpRequest<T> extends HttpEntityEnclosingRequestBase impleme
|
||||
entity.writeTo((OutputStream)t);
|
||||
return t;
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
throw new PayErrorException(new PayException("InstantiationException", e.getMessage()));
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
throw new PayErrorException(new PayException("IllegalAccessException", e.getMessage()));
|
||||
}
|
||||
throw new HttpResponseException(statusLine.getStatusCode(), responseType + " 无法进行类型转换");
|
||||
|
||||
}
|
||||
}
|
||||
String charset = "UTF-8";
|
||||
@@ -174,7 +218,7 @@ public class ClientHttpRequest<T> extends HttpEntityEnclosingRequestBase impleme
|
||||
try {
|
||||
return JSON.parseObject(result, responseType);
|
||||
}catch (JSONException e){
|
||||
throw new PayErrorException(new PayException("failure", "类型转化异常,contentType:" + entity.getContentType().getValue(), result));
|
||||
throw new PayErrorException(new PayException("failure", String.format("类型转化异常,contentType: %s\n%s", entity.getContentType().getValue(), e.getMessage() ), result));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.egzosn.pay.common.util;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.egzosn.pay.common.bean.result.PayException;
|
||||
import com.egzosn.pay.common.exception.PayErrorException;
|
||||
import org.jdom2.Document;
|
||||
import org.jdom2.Element;
|
||||
import org.jdom2.JDOMException;
|
||||
@@ -38,9 +40,9 @@ public class XML {
|
||||
try (InputStream in = new ByteArrayInputStream(content.getBytes("UTF-8"))){
|
||||
return (JSONObject) inputStream2Map(in, null);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new PayErrorException(new PayException("IOException", e.getMessage()));
|
||||
}
|
||||
return null;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -58,9 +60,8 @@ public class XML {
|
||||
try {
|
||||
return (JSONObject)inputStream2Map(in, null);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new PayErrorException(new PayException("IOException", e.getMessage()));
|
||||
}
|
||||
return null;
|
||||
|
||||
|
||||
}
|
||||
@@ -95,7 +96,7 @@ public class XML {
|
||||
m.put(k, v);
|
||||
}
|
||||
} catch (JDOMException e) {
|
||||
e.printStackTrace();
|
||||
throw new PayErrorException(new PayException("JDOMException", e.getMessage()));
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ public enum SignUtils {
|
||||
* @param characterEncoding 编码格式
|
||||
* @return 签名结果
|
||||
*/
|
||||
@Override
|
||||
public boolean verify(String text, String sign, String key, String characterEncoding) {
|
||||
return com.egzosn.pay.common.util.sign.encrypt.MD5.verify(text, sign, key, characterEncoding);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user