移除已废弃的字段与方法

This commit is contained in:
egzosn
2021-01-17 22:38:11 +08:00
parent 0f9439fd4e
commit c6cfd2e8d1
39 changed files with 1099 additions and 1083 deletions

View File

@@ -28,7 +28,7 @@ public class AliPayConfigStorage extends BasePayConfigStorage {
/**
* 商户应用id
*/
private String appid;
private String appId;
/**
* 商户签约拿到的pid,partner_id的简称合作伙伴身份等同于 partner
*/
@@ -73,15 +73,30 @@ public class AliPayConfigStorage extends BasePayConfigStorage {
this.appAuthToken = appAuthToken;
}
public void setAppid(String appid) {
this.appid = appid;
public void setAppid(String appId) {
this.appId = appId;
}
@Override
@Deprecated
public String getAppid() {
return appid;
return appId;
}
/**
* 应用id
* 纠正名称
*
* @return 应用id
*/
@Override
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
@Override
public String getPid() {
@@ -152,7 +167,8 @@ public class AliPayConfigStorage extends BasePayConfigStorage {
InputStream aliPayCertStream = certStoreType.getInputStream(aliPayCert);
InputStream aliPayRootCertStream = certStoreType.getInputStream(aliPayRootCert)) {
this.certEnvironment = new CertEnvironment(merchantCertStream, aliPayCertStream, aliPayRootCertStream);
} catch (IOException e) {
}
catch (IOException e) {
throw new PayErrorException(new PayException("读取证书异常", e.getMessage()));
}
}

View File

@@ -123,7 +123,6 @@ public class AliPayService extends BasePayService<AliPayConfigStorage> {
* @param sign 比对的签名结果
* @return 生成的签名结果
*/
@Override
public boolean signVerify(Map<String, Object> params, String sign) {
if (params instanceof JSONObject) {
@@ -171,7 +170,6 @@ public class AliPayService extends BasePayService<AliPayConfigStorage> {
* @param id 业务id, 数据的真实性.
* @return true通过
*/
@Override
public boolean verifySource(String id) {
return true;
}
@@ -281,10 +279,11 @@ public class AliPayService extends BasePayService<AliPayConfigStorage> {
switch ((AliTransactionType) order.getTransactionType()) {
case SWEEPPAY:
bizContent.put("qr_code_timeout_express", DateUtils.minutesRemaining(order.getExpirationTime()) + "m");
break;
case PAGE:
case WAP:
case APP:
bizContent.put("time_expire", DateUtils.formatDate(order.getExpirationTime(), "yyyy-MM-dd HH:mm"));
bizContent.put("time_expire", DateUtils.formatDate(order.getExpirationTime(), DateUtils.YYYY_MM_DD_HH_MM_SS));
break;
default:
}
@@ -526,7 +525,9 @@ public class AliPayService extends BasePayService<AliPayConfigStorage> {
parameters.put(BIZ_CONTENT, JSON.toJSONString(bizContent));
//设置签名
setSign(parameters);
final AliRefundResult refundResult = AliRefundResult.create(requestTemplate.getForObject(getReqUrl() + "?" + UriVariables.getMapToParameters(parameters), JSONObject.class));
JSONObject result = requestTemplate.getForObject(getReqUrl() + "?" + UriVariables.getMapToParameters(parameters), JSONObject.class);
JSONObject refundResponse = result.getJSONObject("alipay_trade_refund_response");
AliRefundResult refundResult = AliRefundResult.create(refundResponse);
refundResult.setOutRequestNo(refundOrder.getRefundNo());
return refundResult;
}
@@ -587,8 +588,6 @@ public class AliPayService extends BasePayService<AliPayConfigStorage> {
* @param transactionType 交易类型
* @return 返回支付方对应接口的结果
*/
@Override
public Map<String, Object> secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType) {
if (transactionType == AliTransactionType.REFUND) {

View File

@@ -3,51 +3,61 @@ package com.egzosn.pay.baidu.api;
import com.egzosn.pay.common.api.BasePayConfigStorage;
public class BaiduPayConfigStorage extends BasePayConfigStorage {
private String appid;
private String appId;
private String dealId;
@Override
@Deprecated
public String getAppid() {
return this.appid;
return this.appId;
}
@Override
public String getPid() {
return getDealId();
}
@Override
public String getSeller() {
throw new UnsupportedOperationException("不支持");
}
public String getDealId() {
return dealId;
}
public void setDealId(String dealId) {
this.dealId = dealId;
}
public String getAppKey() {
return this.getKeyPrivate();
}
public void setAppKey(String appKey) {
setKeyPrivate(appKey);
}
@Override
public String getKeyPublic() {
return super.getKeyPrivate();
}
@Override
public void setKeyPublic(String keyPublic) {
super.setKeyPublic(keyPublic);
}
public void setAppid(String appid) {
this.appid = appid;
public void setAppid(String appId) {
this.appId = appId;
}
@Override
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
}

View File

@@ -1,14 +1,25 @@
package com.egzosn.pay.baidu.api;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.baidu.bean.BaiduPayOrder;
import com.egzosn.pay.baidu.bean.BaiduRefundOrder;
import com.egzosn.pay.baidu.bean.BaiduTransactionType;
import com.egzosn.pay.baidu.bean.type.AuditStatus;
import com.egzosn.pay.baidu.util.Asserts;
import com.egzosn.pay.common.api.BasePayService;
import com.egzosn.pay.common.bean.*;
import com.egzosn.pay.common.bean.BaseRefundResult;
import com.egzosn.pay.common.bean.CurType;
import com.egzosn.pay.common.bean.MethodType;
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.TransactionType;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.common.http.UriVariables;
import com.egzosn.pay.common.util.DateUtils;
@@ -16,11 +27,6 @@ import com.egzosn.pay.common.util.Util;
import com.egzosn.pay.common.util.sign.SignUtils;
import com.egzosn.pay.common.util.str.StringUtils;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class BaiduPayService extends BasePayService<BaiduPayConfigStorage> {
public static final String APP_KEY = "appKey";
@@ -63,7 +69,7 @@ public class BaiduPayService extends BasePayService<BaiduPayConfigStorage> {
if (!RESPONSE_SUCCESS.equals(params.get(RESPONSE_STATUS))) {
return false;
}
return signVerify(params, String.valueOf(params.get(RSA_SIGN))) && verifySource(String.valueOf(params.get(TP_ORDER_ID)));
return signVerify(params, String.valueOf(params.get(RSA_SIGN)));
}
/**
@@ -73,7 +79,6 @@ public class BaiduPayService extends BasePayService<BaiduPayConfigStorage> {
* @param sign 签名原文
* @return 结果
*/
@Override
public boolean signVerify(Map<String, Object> params, String sign) {
String rsaSign = String.valueOf(params.get(RSA_SIGN));
String targetRsaSign = getRsaSign(params, RSA_SIGN);
@@ -81,10 +86,6 @@ public class BaiduPayService extends BasePayService<BaiduPayConfigStorage> {
return StringUtils.equals(rsaSign, targetRsaSign);
}
@Override
public boolean verifySource(String id) {
return true;
}
/**
* 返回创建的订单信息
@@ -439,7 +440,6 @@ public class BaiduPayService extends BasePayService<BaiduPayConfigStorage> {
* @param transactionType 交易类型
* @return 结果
*/
@Override
public Map<String, Object> secondaryInterface(Object orderId,
String siteId,
TransactionType transactionType) {

View File

@@ -4,8 +4,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import com.egzosn.pay.common.bean.MsgType;
/**
* 支付基础配置存储
*
@@ -51,12 +49,6 @@ public abstract class BasePayConfigStorage implements PayConfigStorage {
*/
private String payType;
/**
* 消息来源类型
*/
@Deprecated
private MsgType msgType;
/**
* 访问令牌 每次请求其他方法都要传入的值
@@ -158,37 +150,36 @@ public abstract class BasePayConfigStorage implements PayConfigStorage {
this.payType = payType;
}
@Override
public MsgType getMsgType() {
return msgType;
}
public void setMsgType(MsgType msgType) {
this.msgType = msgType;
}
/**
* 获取访问令牌
* @return 访问令牌
*
* @return 访问令牌
*/
public String getAccessToken() {
return this.accessToken;
}
/**
* 获取access token锁
*
* @return access token锁
*/
public Lock getAccessTokenLock() {
return this.accessTokenLock;
}
/**
* 强制将access token过期掉
* @return 过期时间
*
* @return 过期时间
*/
public long getExpiresTime() {
return expiresTime;
}
/**
* 访问令牌是否过期
*
* @return true过期
*/
public boolean isAccessTokenExpired() {
@@ -251,7 +242,7 @@ public abstract class BasePayConfigStorage implements PayConfigStorage {
@Override
public Map<String, Object> getAttrs() {
if (null == attr){
if (null == attr) {
attr = new HashMap<>();
}
return attr;
@@ -265,7 +256,8 @@ public abstract class BasePayConfigStorage implements PayConfigStorage {
/**
* 添加配置信息
* @param key key
*
* @param key key
* @param value 值
*/
public void addAttr(String key, Object value) {

View File

@@ -21,9 +21,7 @@ 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.TransactionType;
import com.egzosn.pay.common.bean.TransferOrder;
import com.egzosn.pay.common.exception.PayErrorException;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.common.http.HttpRequestTemplate;
import com.egzosn.pay.common.util.MatrixToImageWriter;
@@ -112,7 +110,8 @@ public abstract class BasePayService<PC extends PayConfigStorage> implements Pay
String base64ClientID = null;
try {
base64ClientID = com.egzosn.pay.common.util.sign.encrypt.Base64.encode(String.format("%s:%s", user, password).getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
}
catch (UnsupportedEncodingException e) {
LOG.error(e);
}
@@ -154,10 +153,12 @@ public abstract class BasePayService<PC extends PayConfigStorage> implements Pay
Map orderInfo = orderInfo(order);
return buildRequest(orderInfo, MethodType.POST);
}
/**
* app支付
*
* @param order 订单信息
* @param <O> 预订单类型
* @param <O> 预订单类型
* @return 对应app所需参数信息
*/
@Override
@@ -173,7 +174,7 @@ public abstract class BasePayService<PC extends PayConfigStorage> implements Pay
*/
@Override
public <O extends PayOrder> BufferedImage genQrPay(O order) {
return MatrixToImageWriter.writeInfoToJpgBuff(getQrPay(order));
return MatrixToImageWriter.writeInfoToJpgBuff(getQrPay(order));
}
/**
@@ -199,7 +200,8 @@ public abstract class BasePayService<PC extends PayConfigStorage> implements Pay
if (valueStr.equals(new String(valueStr.getBytes("iso8859-1"), "iso8859-1"))) {
valueStr = new String(valueStr.getBytes("iso8859-1"), payConfigStorage.getInputCharset());
}
} catch (UnsupportedEncodingException e) {
}
catch (UnsupportedEncodingException e) {
LOG.error(e);
}
}
@@ -265,7 +267,6 @@ public abstract class BasePayService<PC extends PayConfigStorage> implements Pay
}
/**
* 申请退款接口
*
@@ -281,7 +282,6 @@ public abstract class BasePayService<PC extends PayConfigStorage> implements Pay
}
/**
* 查询退款
*
@@ -309,19 +309,6 @@ public abstract class BasePayService<PC extends PayConfigStorage> implements Pay
return callback.perform(downloadbill(billDate, billType));
}
/**
* @param tradeNoOrBillDate 支付平台订单号或者账单类型, 具体请 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link PayErrorException}
* @param outTradeNoBillType 商户单号或者 账单类型
* @param transactionType 交易类型
* @param callback 处理器
* @param <T> 返回类型
* @return 返回支付方对应接口的结果
*/
@Override
public <T> T secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType, Callback<T> callback) {
return callback.perform(secondaryInterface(tradeNoOrBillDate, outTradeNoBillType, transactionType));
}
/**
* 转账
*
@@ -450,12 +437,13 @@ public abstract class BasePayService<PC extends PayConfigStorage> implements Pay
/**
* 预订单回调处理器,用于订单信息的扩展
* 签名之前使用
* 如果需要进行扩展请重写该方法即可
* 如果需要进行扩展请重写该方法即可
*
* @param orderInfo 预订单信息
* @param orderInfo 订单信息
* @return 处理后订单信息
*/
public <O extends PayOrder> Map<String, Object> preOrderHandler(Map<String, Object> orderInfo, O payOrder){
public <O extends PayOrder> Map<String, Object> preOrderHandler(Map<String, Object> orderInfo, O payOrder) {
return orderInfo;
}

View File

@@ -1,7 +1,6 @@
package com.egzosn.pay.common.api;
import com.egzosn.pay.common.bean.Attrs;
import com.egzosn.pay.common.bean.MsgType;
/**
* 支付客户端配置存储
@@ -23,10 +22,21 @@ public interface PayConfigStorage extends Attrs {
/**
* 应用id
* 纠正名称
*
* @return 应用id
* @see #getAppId()
*/
@Deprecated
String getAppid();
/**
* 应用id
* 纠正名称
*
* @return 应用id
*/
String getAppid();
String getAppId();
/**
* 合作商唯一标识
@@ -100,17 +110,6 @@ public interface PayConfigStorage extends Attrs {
*/
String getPayType();
/**
* 消息类型
*
* @return "text" 或者 "xml"json
* @see #getMsgType
* @see MsgType
*/
@Deprecated
MsgType getMsgType();
/**
* 应该是线程安全的
*

View File

@@ -1,11 +1,5 @@
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;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -14,6 +8,13 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.egzosn.pay.common.bean.PayMessage;
import com.egzosn.pay.common.bean.PayOutMessage;
import com.egzosn.pay.common.util.LogExceptionHandler;
/**
* <pre>
* 支付消息路由器通过代码化的配置把来自支付的消息交给handler处理
@@ -124,15 +125,13 @@ public class PayMessageRouter {
* 处理支付消息
*
* @param payMessage 支付消息
* @param storage 支付配置
* @param storage 支付配置
* @return 支付输出结果
*/
public PayOutMessage route(Map<String, Object> payMessage, PayConfigStorage storage) {
PayMessage message = payService.createMessage(payMessage);
message.setPayType(storage.getPayType());
if (null != storage.getMsgType()){
message.setMsgType(storage.getMsgType().name());
}
return route(message);
}
@@ -172,7 +171,8 @@ public class PayMessageRouter {
}
})
);
} else {
}
else {
res = rule.service(payMessage, payService, exceptionHandler);
// 在同步操作结束session访问结束
if (LOG.isDebugEnabled()) {
@@ -190,9 +190,11 @@ public class PayMessageRouter {
future.get();
LOG.debug("End session access: async=true, fromPay=" + payMessage.getFromPay());
} catch (InterruptedException e) {
}
catch (InterruptedException e) {
LOG.error("Error happened when wait task finish", e);
} catch (ExecutionException e) {
}
catch (ExecutionException e) {
LOG.error("Error happened when wait task finish", e);
}
}

View File

@@ -1,20 +1,21 @@
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.exception.PayErrorException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import com.egzosn.pay.common.bean.PayMessage;
import com.egzosn.pay.common.bean.PayOutMessage;
import com.egzosn.pay.common.exception.PayErrorException;
/**
* Route规则 路由
* @author egan
*
* @author egan
* <pre>
* email egzosn@gmail.com
* date 2016-6-1 11:28:01
@@ -32,10 +33,6 @@ public class PayMessageRouterRule {
*/
private boolean async = false;
/**
* 消息类型
*/
private String msgType;
/**
* 支付类型
*/
@@ -74,7 +71,7 @@ public class PayMessageRouterRule {
/**
* 设置是否异步执行默认是true
*
* @param async 是否异步执行默认是true
* @param async 是否异步执行默认是true
* @return Route规则
*/
public PayMessageRouterRule async(boolean async) {
@@ -82,21 +79,11 @@ public class PayMessageRouterRule {
return this;
}
/**
* 如果msgType等于某值
*
* @param msgType 消息类型
* @return Route规则
*/
public PayMessageRouterRule msgType(String msgType) {
this.msgType = msgType;
return this;
}
/**
* 如果payType等于某值
*
* @param payType 支付类型
* @param payType 支付类型
* @return Route规则
*/
public PayMessageRouterRule payType(String payType) {
@@ -110,13 +97,12 @@ public class PayMessageRouterRule {
* @param transactionType 交易类型
* @return Route规则
*/
public PayMessageRouterRule transactionType(String ... transactionType) {
public PayMessageRouterRule transactionType(String... transactionType) {
this.transactionType = transactionType;
return this;
}
/**
* 如果subject等于某值
*
@@ -138,10 +124,11 @@ public class PayMessageRouterRule {
this.rSubject = regex;
return this;
}
/**
* 如果subject匹配该正则表达式
*
* @param key 需要匹配支付消息内键的名字
* @param key 需要匹配支付消息内键的名字
* @param regex key值对应的正则
* @return Route规则
*/
@@ -165,7 +152,7 @@ public class PayMessageRouterRule {
/**
* 设置消息拦截器
*
* @param interceptor 消息拦截器
* @param interceptor 消息拦截器
* @param otherInterceptors 其他消息拦截器
* @return Route规则
*/
@@ -192,7 +179,7 @@ public class PayMessageRouterRule {
/**
* 设置消息处理器
*
* @param handler 消息处理器
* @param handler 消息处理器
* @param otherHandlers 其他消息处理器
* @return Route规则
*/
@@ -229,41 +216,41 @@ public class PayMessageRouterRule {
/**
* 将支付事件修正为不区分大小写,
* 比如框架定义的事件常量为
*
* @param payMessage 支付消息
* @return 是否匹配通过
*/
protected boolean test(PayMessage payMessage) {
return (
(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.payType == null || this.payType.equals((payMessage.getPayType() == null ? null : payMessage.getPayType())))
&&
(this.transactionType == null || equalsTransactionType(payMessage.getTransactionType()))
&&
(this.key == null ||this.rValue == null || Pattern
(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()))
&&
(this.rSubject == null || Pattern
.matches(this.rSubject, payMessage.getSubject() == null ? "" : payMessage.getSubject().trim()))
)
)
;
}
/**
* 匹配交易类型
*
* @param transactionType 交易类型
* @return 匹配交易类型
*/
public boolean equalsTransactionType(String transactionType) {
if (null == transactionType){
if (null == transactionType) {
return false;
}
for (String type :this.getTransactionType()){
if (type.toLowerCase().equals((transactionType.toLowerCase()))){
for (String type : this.getTransactionType()) {
if (type.toLowerCase().equals((transactionType.toLowerCase()))) {
return true;
}
}
@@ -273,15 +260,16 @@ public class PayMessageRouterRule {
/**
* 返回支付响应消息
* @param payMessage 支付消息
* @param payService 支付服务
* 返回支付响应消息
*
* @param payMessage 支付消息
* @param payService 支付服务
* @param exceptionHandler 异常处理器
* @return 支付响应消息
*/
protected PayOutMessage service(PayMessage payMessage,
PayService payService,
PayErrorExceptionHandler exceptionHandler) {
PayService payService,
PayErrorExceptionHandler exceptionHandler) {
try {
@@ -301,7 +289,8 @@ public class PayMessageRouterRule {
res = handler.handle(payMessage, context, payService);
}
return res;
} catch (PayErrorException e) {
}
catch (PayErrorException e) {
exceptionHandler.handle(e);
}
return null;
@@ -320,15 +309,6 @@ public class PayMessageRouterRule {
this.async = async;
}
public String getMsgType() {
return msgType;
}
public void setMsgType(String msgType) {
this.msgType = msgType;
}
public String getPayType() {
return payType;
}

View File

@@ -1,20 +1,26 @@
package com.egzosn.pay.common.api;
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.HttpRequestTemplate;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.util.Date;
import java.util.Map;
import com.egzosn.pay.common.bean.MethodType;
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.bean.TransferOrder;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.common.http.HttpRequestTemplate;
/**
* 支付服务
*
* @author egan
* <pre>
* <pre>
* email egzosn@gmail.com
* date 2016-5-18 14:09:01
* </pre>
@@ -60,53 +66,35 @@ public interface PayService<PC extends PayConfigStorage> {
*/
boolean verify(Map<String, Object> params);
/**
* 签名校验
* 后面版本废弃
* @param params 参数集
* @param sign 签名原文
* @return 签名校验 true通过
*/
@Deprecated
boolean signVerify(Map<String, Object> params, String sign);
/**
* 支付宝需要,微信是否也需要再次校验来源,进行订单查询
* 校验数据来源
* 后面版本废弃
* @param id 业务id, 数据的真实性.
* @return true通过
*/
@Deprecated
boolean verifySource(String id);
/**
* 返回创建的订单信息
*
* @param order 支付订单
* @param <O> 预订单类型
* @return 订单信息
* @param <O> 预订单类型
* @see PayOrder 支付订单信息
*/
<O extends PayOrder>Map<String, Object> orderInfo(O order);
<O extends PayOrder> Map<String, Object> orderInfo(O order);
/**
* 页面转跳支付, 返回对应页面重定向信息
*
* @param order 订单信息
* @param <O> 预订单类型
* @param <O> 预订单类型
* @return 对应页面重定向信息
*/
<O extends PayOrder>String toPay(O order);
<O extends PayOrder> String toPay(O order);
/**
* app支付
*
* @param order 订单信息
* @param <O> 预订单类型
* @param <O> 预订单类型
* @return 对应app所需参数信息
*/
<O extends PayOrder>Map<String, Object> app(O order);
<O extends PayOrder> Map<String, Object> app(O order);
/**
* 创建签名
@@ -118,7 +106,6 @@ public interface PayService<PC extends PayConfigStorage> {
String createSign(String content, String characterEncoding);
/**
* 将请求参数或者请求流转化为 Map
*
@@ -161,27 +148,29 @@ public interface PayService<PC extends PayConfigStorage> {
* 获取输出二维码,用户返回给支付端,
*
* @param order 发起支付的订单信息
* @param <O> 预订单类型
* @param <O> 预订单类型
* @return 返回图片信息,支付时需要的
*/
<O extends PayOrder>BufferedImage genQrPay(O order);
<O extends PayOrder> BufferedImage genQrPay(O order);
/**
* 获取输出二维码信息,
*
* @param order 发起支付的订单信息
* @param <O> 预订单类型
* @param <O> 预订单类型
* @return 返回二维码信息,,支付时需要的
*/
<O extends PayOrder>String getQrPay(O order);
<O extends PayOrder> String getQrPay(O order);
/**
* 刷卡付,pos主动扫码付款(条码付)
* 刷脸付
*
* @param order 发起支付的订单信息
* @param <O> 预订单类型
* @param <O> 预订单类型
* @return 返回支付结果
*/
<O extends PayOrder>Map<String, Object> microPay(O order);
<O extends PayOrder> Map<String, Object> microPay(O order);
/**
* 交易查询接口
@@ -245,7 +234,6 @@ public interface PayService<PC extends PayConfigStorage> {
<T> T cancel(String tradeNo, String outTradeNo, Callback<T> callback);
/**
* 申请退款接口
*
@@ -265,7 +253,6 @@ public interface PayService<PC extends PayConfigStorage> {
<T> T refund(RefundOrder refundOrder, Callback<T> callback);
/**
* 查询退款
*
@@ -305,32 +292,6 @@ public interface PayService<PC extends PayConfigStorage> {
<T> T downloadbill(Date billDate, String billType, Callback<T> callback);
/**
* 通用查询接口
* 接下来移除此方法
* @param tradeNoOrBillDate 支付平台订单号或者账单类型, 具体请
* 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link PayErrorException}
* @param outTradeNoBillType 商户单号或者 账单类型
* @param transactionType 交易类型
* @return 返回支付方对应接口的结果
*/
@Deprecated
Map<String, Object> secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType);
/**
* 通用查询接口
* 接下来移除此方法
* @param tradeNoOrBillDate 支付平台订单号或者账单日期, 具体请 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link PayErrorException}
* @param outTradeNoBillType 商户单号或者 账单类型
* @param transactionType 交易类型
* @param callback 处理器
* @param <T> 返回类型
* @return 返回支付方对应接口的结果
*/
@Deprecated
<T> T secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType, Callback<T> callback);
/**
* 转账
*
@@ -409,6 +370,7 @@ public interface PayService<PC extends PayConfigStorage> {
/**
* 创建消息
*
* @param message 支付平台返回的消息
* @return 支付消息对象
*/
@@ -417,12 +379,13 @@ public interface PayService<PC extends PayConfigStorage> {
/**
* 预订单回调处理器,用于订单信息的扩展
* 签名之前使用
* 如果需要进行扩展请重写该方法即可
* 如果需要进行扩展请重写该方法即可
*
* @param orderInfo 商户平台预订单信息
* @param payOrder 订单信息
* @param <O> 预订单类型
* @param payOrder 订单信息
* @param <O> 预订单类型
* @return 处理后订单信息
*/
<O extends PayOrder>Map<String, Object> preOrderHandler(Map<String, Object> orderInfo, O payOrder);
<O extends PayOrder> Map<String, Object> preOrderHandler(Map<String, Object> orderInfo, O payOrder);
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright 2002-2017 the original egan or egan.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.egzosn.pay.common.bean;
/**
* 消息类型
* @author: egan
* <pre>
* email egzosn@gmail.com
* date 2016/11/18 0:59
* </pre>
*/
public enum MsgType {
text, xml,json
}

View File

@@ -7,6 +7,7 @@ import java.util.Map;
/**
* 支付回调消息
* 基础实现,具体可根据具体支付回调的消息去实现
*
* @author egan
* <pre>
* email egzosn@gmail.com
@@ -15,8 +16,6 @@ import java.util.Map;
*/
public class PayMessage implements Serializable {
private Map<String, Object> payMessage = null;
@Deprecated
private String msgType;
private String payType;
private String transactionType;
private String fromPay;
@@ -30,16 +29,14 @@ public class PayMessage implements Serializable {
this.payMessage = payMessage;
}
public PayMessage(Map<String, Object> payMessage, String payType, String msgType) {
public PayMessage(Map<String, Object> payMessage, String payType) {
this.payMessage = payMessage;
this.payType = payType;
this.msgType = msgType;
}
public PayMessage(Map<String, Object> payMessage, String msgType, String payType, String transactionType) {
public PayMessage(Map<String, Object> payMessage, String payType, String transactionType) {
this.payMessage = payMessage;
this.msgType = msgType;
this.payType = payType;
this.transactionType = transactionType;
}
@@ -48,16 +45,6 @@ public class PayMessage implements Serializable {
this.payMessage = payMessage;
}
@Deprecated
public String getMsgType() {
return msgType;
}
@Deprecated
public void setMsgType(String msgType) {
this.msgType = msgType;
}
public String getPayType() {
return payType;
@@ -72,7 +59,7 @@ public class PayMessage implements Serializable {
}
public void setTransactionType(String transactionType) {
this.transactionType = transactionType;
this.transactionType = transactionType;
}
public String getFromPay() {
@@ -90,28 +77,31 @@ public class PayMessage implements Serializable {
public void setDescribe(String describe) {
this.describe = describe;
}
public String getDiscount(){
public String getDiscount() {
return (String) payMessage.get("discount");
}
public String getSubject(){
public String getSubject() {
return (String) payMessage.get("subject");
}
/////////微信与支付宝共用
public String getOutTradeNo(){
public String getOutTradeNo() {
return (String) payMessage.get("out_trade_no");
}
public String getSign(){
public String getSign() {
return (String) payMessage.get("sign");
}
public Number getTotalFee(){
public Number getTotalFee() {
String totalFee = (String) payMessage.get("total_fee");
if (null == totalFee || "".equals(totalFee)){ return 0; }
if (isNumber(totalFee)){
if (null == totalFee || "".equals(totalFee)) {
return 0;
}
if (isNumber(totalFee)) {
return new BigDecimal(totalFee);
}
return 0;
@@ -120,13 +110,11 @@ public class PayMessage implements Serializable {
/////////微信与支付宝共用
public boolean isNumber(String str){
public boolean isNumber(String str) {
return str.matches("^(-?[1-9]\\d*\\.?\\d*)|(-?0\\.\\d*[1-9])|(-?[0])|(-?[0]\\.\\d*)$");
}
@Override
public String toString() {
return payMessage.toString();
@@ -137,5 +125,4 @@ public class PayMessage implements Serializable {
}
}

View File

@@ -1,15 +1,16 @@
package com.egzosn.pay.common.bean;
import java.io.Serializable;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.common.bean.outbuilder.JsonBuilder;
import com.egzosn.pay.common.bean.outbuilder.TextBuilder;
import com.egzosn.pay.common.bean.outbuilder.XmlBuilder;
import java.io.Serializable;
/**
* 支付回调通知返回消息
* @author egan
* 支付回调通知返回消息
*
* @author egan
* <pre>
* email egzosn@gmail.com
* date 2016-6-1 11:40:30
@@ -17,7 +18,6 @@ import java.io.Serializable;
*/
public abstract class PayOutMessage implements Serializable {
protected String content;
protected String msgType;
public String getContent() {
@@ -28,34 +28,32 @@ public abstract class PayOutMessage implements Serializable {
this.content = content;
}
public String getMsgType() {
return msgType;
}
public void setMsgType(String msgType) {
this.msgType = msgType;
}
/**
* 获得文本消息builder
*
* @return 文本消息builder
*/
public static TextBuilder TEXT() {
return new TextBuilder();
}
/**
* 获得XML消息builder
*
* @return XML消息builder
*/
public static XmlBuilder XML() {
return new XmlBuilder();
}
/**
* 获得Json消息builder
*
* @return Json消息builder
*/
public static JsonBuilder JSON() {
return new JsonBuilder(new JSONObject());
}
public abstract String toMessage();
}

View File

@@ -1,19 +1,18 @@
package com.egzosn.pay.common.bean.outbuilder;
import com.egzosn.pay.common.bean.MsgType;
import com.egzosn.pay.common.bean.PayOutMessage;
/**
* @author egan
* <pre>
* <pre>
* email egzosn@gmail.com
* date 2016-6-1 11:40:30
* </pre>
*/
public class PayJsonOutMessage extends PayOutMessage{
public class PayJsonOutMessage extends PayOutMessage {
public PayJsonOutMessage() {
this.msgType = MsgType.json.name();
}
@Override

View File

@@ -1,6 +1,5 @@
package com.egzosn.pay.common.bean.outbuilder;
import com.egzosn.pay.common.bean.MsgType;
import com.egzosn.pay.common.bean.PayOutMessage;
/**
@@ -13,7 +12,6 @@ import com.egzosn.pay.common.bean.PayOutMessage;
public class PayTextOutMessage extends PayOutMessage{
public PayTextOutMessage() {
this.msgType = MsgType.text.name();
}
@Override

View File

@@ -1,6 +1,5 @@
package com.egzosn.pay.common.bean.outbuilder;
import com.egzosn.pay.common.bean.MsgType;
import com.egzosn.pay.common.bean.PayOutMessage;
/**
@@ -15,7 +14,6 @@ public class PayXmlOutMessage extends PayOutMessage{
private String code;
public PayXmlOutMessage() {
this.msgType = MsgType.xml.name();
}
public String getCode() {

View File

@@ -1,14 +1,13 @@
package com.egzosn.pay.common.http;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.common.bean.result.PayException;
import com.egzosn.pay.common.exception.PayErrorException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.common.bean.result.PayException;
import com.egzosn.pay.common.exception.PayErrorException;
/**
* URL表达式处理器
@@ -23,22 +22,22 @@ public class UriVariables {
/**
* 依次匹配
* @param uri 匹配的uri带代表式
*
* @param uri 匹配的uri带代表式
* @param uriVariables 匹配表达式的值
* @return 匹配完的url
* <code>
* System.out.println(getUri(&quot;http://egan.in/{a}/ba/{a1}?{bb}={a1}&quot;, &quot;no1&quot;, &quot;no2&quot;, &quot;no3&quot;, &quot;no4&quot;));
* 结果 http://egan.in/no1/ba/no2?no3=no4
* System.out.println(getUri(&quot;http://egan.in/{a}/ba/{a1}?{bb}={a1}&quot;, &quot;no1&quot;, &quot;no2&quot;, &quot;no3&quot;, &quot;no4&quot;));
* 结果 http://egan.in/no1/ba/no2?no3=no4
* </code>
*
*/
public static String getUri(String uri, Object... uriVariables) {
if (null == uriVariables){
if (null == uriVariables) {
return uri;
}
for (Object variable : uriVariables){
if (null == variable){
for (Object variable : uriVariables) {
if (null == variable) {
continue;
}
uri = uri.replaceFirst("\\{\\w+\\}", variable.toString());
@@ -47,29 +46,29 @@ public class UriVariables {
}
/**
* 匹配Map.key
* @param uri 匹配的uri带代表式
*
* @param uri 匹配的uri带代表式
* @param uriVariables 匹配表达式的值
* @return 匹配完的url
* <code>
* Map&lt;String, Object&gt; uriVariable = new HashMap&lt;String, Object&gt;();
* uriVariable.put(&quot;a&quot;, &quot;no1&quot;);
* uriVariable.put(&quot;a1&quot;, &quot;no2&quot;);
* uriVariable.put(&quot;bb&quot;, &quot;no3&quot;);
* System.out.println(getUri(&quot;http://egan.in/{a}/ba/{a1}?{bb}={a1}&quot;, uriVariable));
* 结果 http://egan.in/no1/ba/no2?no3=no2
* Map&lt;String, Object&gt; uriVariable = new HashMap&lt;String, Object&gt;();
* uriVariable.put(&quot;a&quot;, &quot;no1&quot;);
* uriVariable.put(&quot;a1&quot;, &quot;no2&quot;);
* uriVariable.put(&quot;bb&quot;, &quot;no3&quot;);
* System.out.println(getUri(&quot;http://egan.in/{a}/ba/{a1}?{bb}={a1}&quot;, uriVariable));
* 结果 http://egan.in/no1/ba/no2?no3=no2
* </code>
*/
public static String getUri(String uri, Map<String, Object> uriVariables) {
if (null == uriVariables){
if (null == uriVariables) {
return uri;
}
for (Map.Entry<String, Object> entry : uriVariables.entrySet()) {
Object uriVariable = entry.getValue();
if (null == uriVariable){
if (null == uriVariable) {
continue;
}
@@ -79,15 +78,15 @@ public class UriVariables {
}
/**
* Map转化为对应得参数字符串
*
* @param pe 参数
* @return 参数字符串
*/
public static String getMapToParameters(Map pe){
public static String getMapToParameters(Map<String, ?> pe) {
StringBuilder builder = new StringBuilder();
for (Map.Entry entry : (Set<Map.Entry>)pe.entrySet()) {
for (Map.Entry<String, ?> entry : pe.entrySet()) {
Object o = entry.getValue();
if (null == o) {
@@ -106,14 +105,15 @@ public class UriVariables {
continue;
}
String value = os[i].toString().trim();
valueStr += (i == len - 1) ? value : value + ",";
valueStr += (i == len - 1) ? value : value + ",";
}
builder.append(entry.getKey()).append("=").append(URLEncoder.encode(valueStr, "utf-8")).append("&");
continue;
}
builder.append(entry.getKey()).append("=").append(URLEncoder.encode( entry.getValue().toString(), "utf-8")).append("&");
} catch (UnsupportedEncodingException e) {
builder.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue().toString(), "utf-8")).append("&");
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
@@ -129,7 +129,7 @@ public class UriVariables {
* @param str 需要解析的字符串
* @return 解析的结果map
*/
public static JSONObject getParametersToMap (String str) {
public static JSONObject getParametersToMap(String str) {
JSONObject map = new JSONObject();
int len = str.length();
@@ -148,16 +148,19 @@ public class UriVariables {
key = temp.toString();
temp.setLength(0);
isKey = false;
} else {
}
else {
temp.append(curChar);
}
} else {// 如果当前生成的是value
}
else {// 如果当前生成的是value
if (isOpen) {
if (curChar == openName) {
isOpen = false;
}
} else {//如果没开启嵌套
}
else {//如果没开启嵌套
if (curChar == '{') {//如果碰到,就开启嵌套
isOpen = true;
openName = '}';
@@ -171,7 +174,8 @@ public class UriVariables {
putKeyValueToMap(temp, isKey, key, map);
temp.setLength(0);
isKey = true;
} else {
}
else {
temp.append(curChar);
}
}
@@ -182,14 +186,15 @@ public class UriVariables {
return map;
}
private static void putKeyValueToMap (StringBuilder temp, boolean isKey, String key, Map<String, Object> map) {
private static void putKeyValueToMap(StringBuilder temp, boolean isKey, String key, Map<String, Object> map) {
if (isKey) {
key = temp.toString();
if (key.length() == 0) {
throw new PayErrorException(new PayException("QString format illegal", "内容格式有误"));
}
map.put(key, "");
} else {
}
else {
if (key.length() == 0) {
throw new PayErrorException(new PayException("QString format illegal", "内容格式有误"));
}

View File

@@ -2,6 +2,22 @@
package com.egzosn.pay.demo.controller;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.egzosn.pay.ali.api.AliPayConfigStorage;
import com.egzosn.pay.ali.api.AliPayService;
import com.egzosn.pay.ali.bean.AliRefundResult;
@@ -18,20 +34,6 @@ import com.egzosn.pay.common.util.sign.SignUtils;
import com.egzosn.pay.demo.request.QueryOrder;
import com.egzosn.pay.demo.service.handler.AliPayMessageHandler;
import com.egzosn.pay.demo.service.interceptor.AliPayMessageInterceptor;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
@@ -48,22 +50,24 @@ public class AliPayController {
private AliPayService service = null;
@Resource
private AutowireCapableBeanFactory spring;
/**
* 设置普通公钥的方式
* 普通公钥方式与证书公钥方式为两者取其一的方式
* @param aliPayConfigStorage 支付宝配置信息
*
* @param aliPayConfigStorage 支付宝配置信息
*/
private static void keyPublic(AliPayConfigStorage aliPayConfigStorage){
private static void keyPublic(AliPayConfigStorage aliPayConfigStorage) {
aliPayConfigStorage.setKeyPublic("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIgHnOn7LLILlKETd6BFRJ0GqgS2Y3mn1wMQmyh9zEyWlz5p1zrahRahbXAfCfSqshSNfqOmAQzSHRVjCqjsAw1jyqrXaPdKBmr90DIpIxmIyKXv4GGAkPyJ/6FTFY99uhpiq0qadD/uSzQsefWo0aTvP/65zi3eof7TcZ32oWpwIDAQAB");
}
/**
* 设置证书公钥信息
* 普通公钥方式与证书公钥方式为两者取其一的方式
*
* @param aliPayConfigStorage 支付宝配置信息
*/
private static void certKeyPublic(AliPayConfigStorage aliPayConfigStorage){
private static void certKeyPublic(AliPayConfigStorage aliPayConfigStorage) {
//设置为证书方式
aliPayConfigStorage.setCertSign(true);
//设置证书存储方式,这里为路径
@@ -79,10 +83,10 @@ public class AliPayController {
aliPayConfigStorage.setPid("2088102169916436");
aliPayConfigStorage.setAppid("2016080400165436");
//普通公钥方式与证书公钥方式为两者取其一的方式
// keyPublic(aliPayConfigStorage);
certKeyPublic(aliPayConfigStorage);
// aliPayConfigStorage.setKeyPrivate("MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKroe/8h5vC4L6T+B2WdXiVwGsMvUKgb2XsKix6VY3m2wcf6tyzpNRDCNykbIwGtaeo7FshN+qZxdXHLiIam9goYncBit/8ojfLGy2gLxO/PXfzGxYGs0KsDZ+ryVPPmE34ZZ8jiJpR0ygzCFl8pN3QJPJRGTJn5+FTT9EF/9zyZAgMBAAECgYAktngcYC35u7cQXDk+jMVyiVhWYU2ULxdSpPspgLGzrZyG1saOcTIi/XVX8Spd6+B6nmLQeF/FbU3rOeuD8U2clzul2Z2YMbJ0FYay9oVZFfp5gTEFpFRTVfzqUaZQBIjJe/xHL9kQVqc5xHlE/LVA27/Kx3dbC35Y7B4EVBDYAQJBAOhsX8ZreWLKPhXiXHTyLmNKhOHJc+0tFH7Ktise/0rNspojU7o9prOatKpNylp9v6kux7migcMRdVUWWiVe+4ECQQC8PqsuEz7B0yqirQchRg1DbHjh64bw9Kj82EN1/NzOUd53tP9tg+SO97EzsibK1F7tOcuwqsa7n2aY48mQ+y0ZAkBndA2xcRcnvOOjtAz5VO8G7R12rse181HjGfG6AeMadbKg30aeaGCyIxN1loiSfNR5xsPJwibGIBg81mUrqzqBAkB+K6rkaPXJR9XtzvdWb/N3235yPkDlw7Z4MiOVM3RzvR/VMDV7m8lXoeDde2zQyeMOMYy6ztwA6WgE1bhGOnQRAkEAouUBv1sVdSBlsexX15qphOmAevzYrpufKgJIRLFWQxroXMS7FTesj+f+FmGrpPCxIde1dqJ8lqYLTyJmbzMPYw==");
aliPayConfigStorage.setKeyPrivate("MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCw7MD2Cwv/jnXssFjXnGx3JlGF57gJa2aYbJRV8MnNiPVpX4Ha+8ZjnQDhvkrWH4hHmzcujOr213HqloMpUSYBzCPiXGVRUUvdimejcHHTod7nI4g6nztzzfey/TXNDHmp7vY3pOIcjB0Zn0pkNAz2tKAFkqb4raHOqTB0QA0zD24Cn+26J2UJyYRcgeH0GtSQuUrm7yaGsuKakh+qtgWF6R71n5PMGOTQ5LH3i0WVHfCBkNGgJC6yC96HR4D7cosoyKD0+lp8UB/NVUWl7Tt/KLOgFUwh0GKSYFfv56O/VBV2+xqCGE4PlZESfVuOqz5vjjxzw3xDAUJrV8hSX/AJAgMBAAECggEBAKE0d3U4B4yo/2XUIH8EdgfykCFUSum6RFbpyBauORHfksyaSzV+ZvtomN8XhhSn0oJ8OMFfgM+86nz2+zdwSxMkMCYWTfLUAi4v59KRqAVO3kz4oS3Y3FDeAK3D7XuRvGFL7GgzAhtEx1cLPrsiehVn6s5pG15GxsIIgq/JlL1J88wn1zENLrVHmD6z/JpXvfb/RS1yR+5lyoohp4g0Ph9jJ3bCyUbRpK0QkPEzgAuWL0K2ITCL7PYHNAplI8d2xHHOLF9Qdjyx+ZrQ/RxtqzfyWzhqjsmp2qlgNCxWlt3woS9UhDB+nRvjEoWTJmIOszAMYuj8wGlX+3Ui3ALOdQECgYEA25EqnFPFinUnzgNvB6NYmh5STmZun6s4bUOLqwefKtEvrOtRwTu7sB7NIf37fizG3/MJUWHxiLy2/3ub4d2JxdDNBtJoEqnp6QB12qglCNa4CajdjtJa1dR81F9QvytsqEkmPYXFPPyviB0FcSIDAGMb3IbwvIfzBPY9WY8dJnECgYEAzkg3yKEFBZ8BU0WQ+3hyfKUoAhBEnxouxRSTBcXxwstJRiqaGTVe5aoJGQI+0xS7Z6q07XDtN2t97s6DnRLWbljsX6B64itzNhXRyzjdD3iZDU/KSw7khjhXf8XOZaj9eXmACDiUnkEn1xsM8bLiRGqB8y5f3aMY/RpuACGXnxkCgYEAx/zwT9Vpr1RIfjfYcJ+Su0X0994K0roUukj0tUJK8qf4gcsQ+y1aJe/YLib1ZBaKyj7G9O5+HmqtUAUZld/AdoJZzOXmz2EeYhD+R7wxh1xz4rCBpW3qOKvDS3jJxmZaIOoHv6/RWFxb0WGFrGcrTrX3EaWDLmWxr4pNlP5qsbECgYATllntrBR8/ycyEAX/SuWcHlaZM5BAh0zvm8+GGdCmDYWMqxjs0duL9URd4o+ynWJaKqR5c2KjA4r2tRdcP+Cqo7j2L5fbiAKtnQ7JvEGJaYsm72+nBuf+MrVkRZUepBhFg5r7rNu31zoAO+pTvQetNWvXeozRz93ckrjlPEtYaQKBgQDFwbV92rlRMLjZzlY+o0knoeJBjPQmPdiBTpGNimdy9L4c2Ure7affjcUiYhkKqrK5k5SScJTATgyQ7JF346FdtUtZ/6Kkj1RwJmmprPrDa9CATLoTle7g9OVd4sHT2ITHZMzPaF3ILvzcwJ70AD1xcxCQb+/7sDPmw7Mc8gOA7Q==");
keyPublic(aliPayConfigStorage);
aliPayConfigStorage.setKeyPrivate("MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKroe/8h5vC4L6T+B2WdXiVwGsMvUKgb2XsKix6VY3m2wcf6tyzpNRDCNykbIwGtaeo7FshN+qZxdXHLiIam9goYncBit/8ojfLGy2gLxO/PXfzGxYGs0KsDZ+ryVPPmE34ZZ8jiJpR0ygzCFl8pN3QJPJRGTJn5+FTT9EF/9zyZAgMBAAECgYAktngcYC35u7cQXDk+jMVyiVhWYU2ULxdSpPspgLGzrZyG1saOcTIi/XVX8Spd6+B6nmLQeF/FbU3rOeuD8U2clzul2Z2YMbJ0FYay9oVZFfp5gTEFpFRTVfzqUaZQBIjJe/xHL9kQVqc5xHlE/LVA27/Kx3dbC35Y7B4EVBDYAQJBAOhsX8ZreWLKPhXiXHTyLmNKhOHJc+0tFH7Ktise/0rNspojU7o9prOatKpNylp9v6kux7migcMRdVUWWiVe+4ECQQC8PqsuEz7B0yqirQchRg1DbHjh64bw9Kj82EN1/NzOUd53tP9tg+SO97EzsibK1F7tOcuwqsa7n2aY48mQ+y0ZAkBndA2xcRcnvOOjtAz5VO8G7R12rse181HjGfG6AeMadbKg30aeaGCyIxN1loiSfNR5xsPJwibGIBg81mUrqzqBAkB+K6rkaPXJR9XtzvdWb/N3235yPkDlw7Z4MiOVM3RzvR/VMDV7m8lXoeDde2zQyeMOMYy6ztwA6WgE1bhGOnQRAkEAouUBv1sVdSBlsexX15qphOmAevzYrpufKgJIRLFWQxroXMS7FTesj+f+FmGrpPCxIde1dqJ8lqYLTyJmbzMPYw==");
// certKeyPublic(aliPayConfigStorage);
// aliPayConfigStorage.setKeyPrivate("MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCw7MD2Cwv/jnXssFjXnGx3JlGF57gJa2aYbJRV8MnNiPVpX4Ha+8ZjnQDhvkrWH4hHmzcujOr213HqloMpUSYBzCPiXGVRUUvdimejcHHTod7nI4g6nztzzfey/TXNDHmp7vY3pOIcjB0Zn0pkNAz2tKAFkqb4raHOqTB0QA0zD24Cn+26J2UJyYRcgeH0GtSQuUrm7yaGsuKakh+qtgWF6R71n5PMGOTQ5LH3i0WVHfCBkNGgJC6yC96HR4D7cosoyKD0+lp8UB/NVUWl7Tt/KLOgFUwh0GKSYFfv56O/VBV2+xqCGE4PlZESfVuOqz5vjjxzw3xDAUJrV8hSX/AJAgMBAAECggEBAKE0d3U4B4yo/2XUIH8EdgfykCFUSum6RFbpyBauORHfksyaSzV+ZvtomN8XhhSn0oJ8OMFfgM+86nz2+zdwSxMkMCYWTfLUAi4v59KRqAVO3kz4oS3Y3FDeAK3D7XuRvGFL7GgzAhtEx1cLPrsiehVn6s5pG15GxsIIgq/JlL1J88wn1zENLrVHmD6z/JpXvfb/RS1yR+5lyoohp4g0Ph9jJ3bCyUbRpK0QkPEzgAuWL0K2ITCL7PYHNAplI8d2xHHOLF9Qdjyx+ZrQ/RxtqzfyWzhqjsmp2qlgNCxWlt3woS9UhDB+nRvjEoWTJmIOszAMYuj8wGlX+3Ui3ALOdQECgYEA25EqnFPFinUnzgNvB6NYmh5STmZun6s4bUOLqwefKtEvrOtRwTu7sB7NIf37fizG3/MJUWHxiLy2/3ub4d2JxdDNBtJoEqnp6QB12qglCNa4CajdjtJa1dR81F9QvytsqEkmPYXFPPyviB0FcSIDAGMb3IbwvIfzBPY9WY8dJnECgYEAzkg3yKEFBZ8BU0WQ+3hyfKUoAhBEnxouxRSTBcXxwstJRiqaGTVe5aoJGQI+0xS7Z6q07XDtN2t97s6DnRLWbljsX6B64itzNhXRyzjdD3iZDU/KSw7khjhXf8XOZaj9eXmACDiUnkEn1xsM8bLiRGqB8y5f3aMY/RpuACGXnxkCgYEAx/zwT9Vpr1RIfjfYcJ+Su0X0994K0roUukj0tUJK8qf4gcsQ+y1aJe/YLib1ZBaKyj7G9O5+HmqtUAUZld/AdoJZzOXmz2EeYhD+R7wxh1xz4rCBpW3qOKvDS3jJxmZaIOoHv6/RWFxb0WGFrGcrTrX3EaWDLmWxr4pNlP5qsbECgYATllntrBR8/ycyEAX/SuWcHlaZM5BAh0zvm8+GGdCmDYWMqxjs0duL9URd4o+ynWJaKqR5c2KjA4r2tRdcP+Cqo7j2L5fbiAKtnQ7JvEGJaYsm72+nBuf+MrVkRZUepBhFg5r7rNu31zoAO+pTvQetNWvXeozRz93ckrjlPEtYaQKBgQDFwbV92rlRMLjZzlY+o0knoeJBjPQmPdiBTpGNimdy9L4c2Ure7affjcUiYhkKqrK5k5SScJTATgyQ7JF346FdtUtZ/6Kkj1RwJmmprPrDa9CATLoTle7g9OVd4sHT2ITHZMzPaF3ILvzcwJ70AD1xcxCQb+/7sDPmw7Mc8gOA7Q==");
aliPayConfigStorage.setNotifyUrl("http://pay.egzosn.com/payBack.json");
aliPayConfigStorage.setReturnUrl("http://pay.egzosn.com/payBack.html");
aliPayConfigStorage.setSignType(SignUtils.RSA2.name());
@@ -97,7 +101,7 @@ public class AliPayController {
httpConfigStorage.setMaxTotal(20);
//默认的每个路由的最大连接数
httpConfigStorage.setDefaultMaxPerRoute(10);
service = new AliPayService(aliPayConfigStorage, httpConfigStorage);
service = new AliPayService(aliPayConfigStorage, httpConfigStorage);
//增加支付回调消息拦截器
service.addPayMessageInterceptor(new AliPayMessageInterceptor());
//设置回调消息处理
@@ -105,16 +109,15 @@ public class AliPayController {
}
/**
* 跳到支付页面
* 针对实时支付,即时付款
*
* @param price 金额
* @param price 金额
* @return 跳到支付页面
*/
@RequestMapping(value = "toPay.html", produces = "text/html;charset=UTF-8")
public String toPay( BigDecimal price) {
public String toPay(BigDecimal price) {
//及时收款
PayOrder order = new PayOrder("订单title", "摘要", null == price ? BigDecimal.valueOf(0.01) : price, UUID.randomUUID().toString().replace("-", ""), AliTransactionType.PAGE);
//WAP
@@ -127,8 +130,6 @@ public class AliPayController {
}
/**
* 获取支付预订单信息
*
@@ -148,35 +149,39 @@ public class AliPayController {
/**
* 获取二维码图像
* 二维码支付
* @param price 金额
*
* @param price 金额
* @return 二维码图像
* @throws IOException IOException
*/
@RequestMapping(value = "toQrPay.jpg", produces = "image/jpeg;charset=UTF-8")
public byte[] toQrPay( BigDecimal price) throws IOException {
public byte[] toQrPay(BigDecimal price) throws IOException {
//获取对应的支付账户操作工具可根据账户id
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(service.genQrPay( new PayOrder("订单title", "摘要", null == price ? BigDecimal.valueOf(0.01) : price, System.currentTimeMillis()+"", AliTransactionType.SWEEPPAY)), "JPEG", baos);
ImageIO.write(service.genQrPay(new PayOrder("订单title", "摘要", null == price ? BigDecimal.valueOf(0.01) : price, System.currentTimeMillis() + "", AliTransactionType.SWEEPPAY)), "JPEG", baos);
return baos.toByteArray();
}
/**
* 获取二维码地址
* 二维码支付
* @param price 金额
*
* @param price 金额
* @return 二维码图像
* @throws IOException IOException
*/
@RequestMapping(value = "getQrPay.json")
public String getQrPay(BigDecimal price) throws IOException {
//获取对应的支付账户操作工具可根据账户id
return service.getQrPay( new PayOrder("订单title", "摘要", null == price ? BigDecimal.valueOf(0.01) : price, System.currentTimeMillis()+"", AliTransactionType.SWEEPPAY));
return service.getQrPay(new PayOrder("订单title", "摘要", null == price ? BigDecimal.valueOf(0.01) : price, System.currentTimeMillis() + "", AliTransactionType.SWEEPPAY));
}
/**
* 刷卡付,pos主动扫码付款(条码付)
* @param authCode 授权码,条码等
* @param price 金额
*
* @param authCode 授权码,条码等
* @param price 金额
* @return 支付结果
*/
@RequestMapping(value = "microPay")
@@ -184,7 +189,7 @@ public class AliPayController {
//获取对应的支付账户操作工具可根据账户id
//条码付
PayOrder order = new PayOrder("egan order", "egan order", null == price ? BigDecimal.valueOf(0.01) : price, UUID.randomUUID().toString().replace("-", ""), AliTransactionType.BAR_CODE);
//声波付
//声波付
// PayOrder order = new PayOrder("egan order", "egan order", null == price ? BigDecimal.valueOf(0.01) : price, UUID.randomUUID().toString().replace("-", ""), AliTransactionType.WAVE_CODE);
//设置授权码,条码等
order.setAuthCode(authCode);
@@ -204,15 +209,13 @@ public class AliPayController {
/**
* 支付回调地址 方式一
*
* <p>
* 方式二,{@link #payBack(HttpServletRequest)} 是属于简化方式, 试用与简单的业务场景
*
*
* @param request 请求
*
* @return 返回对应的响应码
* @see #payBack(HttpServletRequest)
* @throws IOException IOException
* @see #payBack(HttpServletRequest)
*/
@Deprecated
@RequestMapping(value = "payBackBefore.json")
@@ -233,15 +236,15 @@ public class AliPayController {
return service.getPayOutMessage("fail", "失败").toMessage();
}
/**
* 支付回调地址
*
* @param request 请求
*
* @return 返回对应的响应码
*
* <p>
* 业务处理在对应的PayMessageHandler里面处理在哪里设置PayMessageHandler详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)}
*
* <p>
* 如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler}
* @throws IOException IOException
*/
@@ -290,6 +293,7 @@ public class AliPayController {
public Map<String, Object> close(QueryOrder order) {
return service.close(order.getTradeNo(), order.getOutTradeNo());
}
/**
* 交易c撤销接口
*
@@ -339,7 +343,6 @@ public class AliPayController {
* 转账
*
* @param order 转账订单
*
* @return 对应的转账结果
*/
@RequestMapping("transfer")
@@ -363,7 +366,6 @@ public class AliPayController {
*
* @param outNo 商户转账订单号
* @param tradeNo 支付平台转账订单号
*
* @return 对应的转账订单
*/
@RequestMapping("transferQuery")

View File

@@ -2,13 +2,37 @@
package com.egzosn.pay.demo.controller;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import static com.egzosn.pay.demo.dao.ApyAccountRepository.apyAccounts;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.ali.api.AliPayService;
import com.egzosn.pay.ali.bean.AliTransactionType;
import com.egzosn.pay.common.api.PayConfigStorage;
import com.egzosn.pay.common.api.PayMessageInterceptor;
import com.egzosn.pay.common.api.PayService;
import com.egzosn.pay.common.bean.*;
import com.egzosn.pay.common.bean.MethodType;
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.TransferOrder;
import com.egzosn.pay.common.http.UriVariables;
import com.egzosn.pay.common.util.MatrixToImageWriter;
import com.egzosn.pay.common.util.str.StringUtils;
@@ -18,22 +42,6 @@ import com.egzosn.pay.demo.request.QueryOrder;
import com.egzosn.pay.demo.service.ApyAccountService;
import com.egzosn.pay.demo.service.PayResponse;
import com.egzosn.pay.wx.bean.WxTransactionType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import static com.egzosn.pay.demo.dao.ApyAccountRepository.apyAccounts;
/**
* 发起支付入口
@@ -76,7 +84,7 @@ public class PayController {
* 跳到支付页面
* 针对实时支付,即时付款
*
* @param request 请求
* @param request 请求
* @param payId 账户id
* @param transactionType 交易类型, 这个针对于每一个 支付类型的对应的几种交易方式
* @param bankType 针对刷卡支付,卡的类型,类型值
@@ -115,6 +123,7 @@ public class PayController {
/**
* 跳到支付页面
* 针对实时支付,即时付款
*
* @param request 请求
* @return 跳到支付页面
*/
@@ -164,7 +173,7 @@ public class PayController {
*
* @param payId 支付账户id
* @param transactionType 交易类型
* @param price 金额
* @param price 金额
* @return 支付预订单信息
*/
@RequestMapping("app")
@@ -188,7 +197,7 @@ public class PayController {
* @return 支付结果
*/
@RequestMapping(value = "microPay")
public Map<String, Object> microPay(Integer payId, String transactionType, BigDecimal price, String authCode) {
public Map<String, Object> microPay(Integer payId, String transactionType, BigDecimal price, String authCode) {
//获取对应的支付账户操作工具可根据账户id
PayResponse payResponse = service.getPayResponse(payId);
@@ -200,7 +209,7 @@ public class PayController {
PayConfigStorage storage = payResponse.getService().getPayConfigStorage();
//校验
if (payResponse.getService().verify(params)) {
PayMessage message = new PayMessage(params, storage.getPayType(), storage.getMsgType().name());
PayMessage message = new PayMessage(params, storage.getPayType());
//支付校验通过后的处理
payResponse.getRouter().route(message);
}
@@ -215,7 +224,6 @@ public class PayController {
* @param payId 账户id
* @param transactionType 交易类型, 这个针对于每一个 支付类型的对应的几种交易方式
* @param price 金额
*
* @return 二维码图像
* @throws IOException IOException
*/
@@ -228,10 +236,12 @@ public class PayController {
ImageIO.write(payResponse.getService().genQrPay(new PayOrder("订单title", "摘要", null == price ? BigDecimal.valueOf(0.01) : price, System.currentTimeMillis() + "", PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType(transactionType))), "JPEG", baos);
return baos.toByteArray();
}
/**
* 获取二维码地址
* 二维码支付
* @param price 金额
*
* @param price 金额
* @return 二维码图像
* @throws IOException IOException
*/
@@ -240,8 +250,9 @@ public class PayController {
//获取对应的支付账户操作工具可根据账户id
//获取对应的支付账户操作工具可根据账户id
PayResponse payResponse = service.getPayResponse(payId);
return payResponse.getService().getQrPay( new PayOrder("订单title", "摘要", null == price ? BigDecimal.valueOf(0.01) : price, System.currentTimeMillis() + "", PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType(transactionType)));
return payResponse.getService().getQrPay(new PayOrder("订单title", "摘要", null == price ? BigDecimal.valueOf(0.01) : price, System.currentTimeMillis() + "", PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType(transactionType)));
}
/**
* 获取一码付二维码图像
* 二维码支付
@@ -249,7 +260,7 @@ public class PayController {
* @param wxPayId 微信账户id
* @param aliPayId 支付宝id
* @param price 金额
* @param request 请求
* @param request 请求
* @return 二维码图像
* @throws IOException IOException
*/
@@ -279,7 +290,7 @@ public class PayController {
* @param wxPayId 微信账户id
* @param aliPayId 支付宝id
* @param price 金额
* @param request 请求
* @param request 请求
* @return 支付宝与微信平台的判断
* @throws IOException IOException
*/
@@ -309,15 +320,13 @@ public class PayController {
}
/**
* 支付回调地址 方式一
* <p>
* 方式二,{@link #payBack(HttpServletRequest, Integer)} 是属于简化方式, 试用与简单的业务场景
*
* @param request 请求
* @param payId 账户id
* @param payId 账户id
* @return 支付是否成功
* @throws IOException IOException
*/
@@ -361,14 +370,14 @@ public class PayController {
* 方式二
*
* @param request 请求
* @param payId 账户id
* @param payId 账户id
* @return 支付是否成功
* @throws IOException IOException
* 拦截器相关增加, 详情查看{@link com.egzosn.pay.common.api.PayService#addPayMessageInterceptor(PayMessageInterceptor)}
* <p>
* 业务处理在对应的PayMessageHandler里面处理在哪里设置PayMessageHandler详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)}
* </p>
* 如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler}
* 拦截器相关增加, 详情查看{@link com.egzosn.pay.common.api.PayService#addPayMessageInterceptor(PayMessageInterceptor)}
* <p>
* 业务处理在对应的PayMessageHandler里面处理在哪里设置PayMessageHandler详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)}
* </p>
* 如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler}
*/
@RequestMapping(value = "payBack{payId}.json")
public String payBack(HttpServletRequest request, @PathVariable Integer payId) throws IOException {
@@ -417,6 +426,7 @@ public class PayController {
/**
* 申请退款接口
*
* @param payId 账户id
* @param order 订单的请求体
* @return 返回支付方申请退款后的结果
@@ -426,7 +436,8 @@ public class PayController {
PayResponse payResponse = service.getPayResponse(payId);
// return payResponse.getService().refund(order.getTradeNo(), order.getOutTradeNo(), order.getRefundAmount(), order.getTotalAmount());
return payResponse.getService().refund(order);
final PayService service = payResponse.getService();
return service.refund(order);
}
/**
@@ -457,22 +468,9 @@ public class PayController {
}
/**
* 通用查询接口,根据 TransactionType 类型进行实现,此接口不包括退款
*
* @param order 订单的请求体
* @return 返回支付方对应接口的结果
*/
@RequestMapping("secondaryInterface")
public Map<String, Object> secondaryInterface(QueryOrder order) {
PayResponse payResponse = service.getPayResponse(order.getPayId());
TransactionType type = PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType(order.getTransactionType());
return payResponse.getService().secondaryInterface(order.getTradeNoOrBillDate(), order.getOutTradeNoBillType(), type);
}
/**
* 转账
*
* @param payId 账户id
* @param order 转账订单
* @return 对应的转账结果
@@ -485,7 +483,8 @@ public class PayController {
/**
* 转账查询
* @param payId 账户id
*
* @param payId 账户id
* @param outNo 商户转账订单号
* @param tradeNo 支付平台转账订单号
* @return 对应的转账订单

View File

@@ -1,6 +1,18 @@
package com.egzosn.pay.demo.controller;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.egzosn.pay.common.api.PayService;
import com.egzosn.pay.common.bean.DefaultCurType;
import com.egzosn.pay.common.bean.PayOrder;
@@ -10,17 +22,6 @@ import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.paypal.api.PayPalConfigStorage;
import com.egzosn.pay.paypal.api.PayPalPayService;
import com.egzosn.pay.paypal.bean.PayPalTransactionType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Map;
import java.util.UUID;
/**
* 发起支付入口
@@ -39,13 +40,13 @@ public class PayPalPayController {
@PostConstruct
public void init() {
PayPalConfigStorage storage = new PayPalConfigStorage();
storage.setClientID("AZ7HTcvrEAxYbzYx_iDZAi06GdqbjhqqQzFgPBFLxm2VUMzwlmiNUBk_y_5QNP4zWKblTuM6ZBAmxScd");
storage.setClientSecret("EBMIjAag6NiRdXZxteTv0amEsmKN345xJv3bN7f_HRXSqcRJlW7PXhYXjI9sk5I4nKYOHgeqzhXCXKFo");
storage.setClientID("AZDS0IhUZvJTO99unlvSDMfbZIP-p-UecYXZdJoweha9LFuqKXKcQIGZgfVaX6oGiAOJAUuJD7JwyTl1");
storage.setClientSecret("EK2YaOrw3oLSDWIRzvb9BWGTjiPPhY1fFUu5ylhUsGYLc_h_dlpJ0hr_LDEkbO9MyKP2P83YcywbPaem");
storage.setTest(true);
//发起付款后的页面转跳地址
storage.setReturnUrl("http://www.egzosn.com/payPal/payBack.json");
//取消按钮转跳地址,这里用异步通知地址的兼容的做法
storage.setNotifyUrl("http://www.egzosn.com/pay/cancel");
storage.setCancelUrl("http://www.egzosn.com/pay/cancel");
service = new PayPalPayService(storage);
//请求连接池配置
@@ -76,11 +77,12 @@ public class PayPalPayController {
String toPayHtml = service.toPay(order);
//某些支付下单时无法设置单号,通过下单后返回对应单号,如 paypal友店。
String outTradeNo = order.getOutTradeNo();
System.out.println("支付订单号:" + outTradeNo + " 这里可以进行回存");
String tradeNo = order.getTradeNo();
System.out.println("支付订单号:" + tradeNo + " 这里可以进行回存");
return toPayHtml;
}
/**
* 申请退款接口
*
@@ -98,10 +100,13 @@ public class PayPalPayController {
}
/* */
/**
* return url
* PayPal确认付款调用的接口
* 用户确认付款后paypal调用的这个方法执行付款
*
* @param request 请求
* @return 付款成功信息
* @throws IOException IOException
@@ -118,17 +123,17 @@ public class PayPalPayController {
return "failure";
}
/* */
/**
* 支付回调地址
*
* @param request 请求
*
* @param request 请求
* @return 结果
* @throws IOException IOException
* 业务处理在对应的PayMessageHandler里面处理在哪里设置PayMessageHandler详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)}
*
* 如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler}
*
* 业务处理在对应的PayMessageHandler里面处理在哪里设置PayMessageHandler详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)}
* <p>
* 如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler}
*/
@RequestMapping(value = "payBack.json")
public String payBack(HttpServletRequest request) throws IOException {

View File

@@ -1,23 +1,30 @@
package com.egzosn.pay.demo.controller;
import com.egzosn.pay.common.bean.*;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.demo.request.QueryOrder;
import com.egzosn.pay.payoneer.api.PayoneerConfigStorage;
import com.egzosn.pay.payoneer.api.PayoneerPayService;
import com.egzosn.pay.payoneer.bean.PayoneerTransactionType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.egzosn.pay.common.bean.DefaultCurType;
import com.egzosn.pay.common.bean.PayOrder;
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.bean.TransferOrder;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.demo.request.QueryOrder;
import com.egzosn.pay.payoneer.api.PayoneerConfigStorage;
import com.egzosn.pay.payoneer.api.PayoneerPayService;
import com.egzosn.pay.payoneer.bean.PayoneerTransactionType;
/**
* @author egan
* email egzosn@gmail.com
@@ -34,7 +41,6 @@ public class PayoneerPayController {
public void init() {
PayoneerConfigStorage configStorage = new PayoneerConfigStorage();
configStorage.setProgramId("商户id");
configStorage.setMsgType(MsgType.json);
configStorage.setInputCharset("utf-8");
configStorage.setUserName("PayoneerPay 用户名");
configStorage.setApiPassword("PayoneerPay API password");
@@ -63,11 +69,12 @@ public class PayoneerPayController {
/**
* 获取授权页面
*
* @param payeeId 用户id
* @return 获取授权页面
*/
@RequestMapping("getAuthorizationPage.json")
public Map<String ,Object> getAuthorizationPage( String payeeId ){
public Map<String, Object> getAuthorizationPage(String payeeId) {
Map<String, Object> data = new LinkedHashMap<>();
data.put("code", 0);
@@ -75,13 +82,14 @@ public class PayoneerPayController {
return data;
}
/**
/**
* 获取授权用户信息,包含用户状态,注册时间,联系人信息,地址信息等等
*
* @param payeeId 用户id
* @return 获取授权用户信息
*/
@RequestMapping("getAuthorizationUser.json")
public Map<String ,Object> getAuthorizationUser( String payeeId ){
public Map<String, Object> getAuthorizationUser(String payeeId) {
Map<String, Object> data = new LinkedHashMap<>();
data.put("code", 0);
@@ -92,36 +100,36 @@ public class PayoneerPayController {
/**
* 主动收款
* @param price 金额
* @param userId 付款用户
*
* @param price 金额
* @param userId 付款用户
* @return 支付结果
*/
@ResponseBody
@RequestMapping(value = "microPay.json")
public Map<String, Object> microPay(BigDecimal price, String userId){
public Map<String, Object> microPay(BigDecimal price, String userId) {
PayOrder order = new PayOrder("Order_payment:", "Order payment", price, UUID.randomUUID().toString().replace("-", ""), PayoneerTransactionType.CHARGE);
//币种
order.setCurType(DefaultCurType.USD);
//设置授权码,条码等
order.setAuthCode( userId);
order.setAuthCode(userId);
//支付结果
Map<String, Object> params = service.microPay(order);
if (10700 == (Integer) params.get(PayoneerPayService.CODE)){
if (10700 == (Integer) params.get(PayoneerPayService.CODE)) {
System.out.println("未授权");
}else if (0 == (Integer) params.get(PayoneerPayService.CODE)){
}
else if (0 == (Integer) params.get(PayoneerPayService.CODE)) {
System.out.println("收款成功");
}
return params;
}
/**
* 用户授权回调地址
*
* @param request 请求
*
* @return 是否成功
* @throws IOException IOException
*/
@@ -166,6 +174,7 @@ public class PayoneerPayController {
public Map<String, Object> close(QueryOrder order) {
return service.close(order.getTradeNo(), order.getOutTradeNo());
}
/**
* 申请退款接口
*
@@ -173,7 +182,7 @@ public class PayoneerPayController {
* @return 返回支付方申请退款后的结果
*/
@RequestMapping("refund")
public Map<String, Object> refund(RefundOrder order) {
public RefundResult refund(RefundOrder order) {
return service.refund(order);
}
@@ -195,7 +204,6 @@ public class PayoneerPayController {
* 转账
*
* @param order 转账订单
*
* @return 对应的转账结果
*/
@RequestMapping("transfer")
@@ -213,7 +221,6 @@ public class PayoneerPayController {
*
* @param outNo 商户转账订单号
* @param tradeNo 支付平台转账订单号
*
* @return 对应的转账订单
*/
@RequestMapping("transferQuery")

View File

@@ -3,16 +3,16 @@
package com.egzosn.pay.demo.dao;
import com.egzosn.pay.common.bean.MsgType;
import java.util.HashMap;
import java.util.Map;
import com.egzosn.pay.common.util.sign.SignUtils;
import com.egzosn.pay.demo.entity.ApyAccount;
import com.egzosn.pay.demo.entity.PayType;
import java.util.HashMap;
import java.util.Map;
/**
* 账户
*
* @author: egan
* email egzosn@gmail.com
* date 2016/11/18 1:21
@@ -21,12 +21,11 @@ import java.util.Map;
public class ApyAccountRepository {
// 这里简单模拟引入orm等框架之后可自行删除
public static Map<Integer, ApyAccount> apyAccounts = new HashMap<>();
public static Map<Integer, ApyAccount> apyAccounts = new HashMap<>();
/**
* 这里简单初始化引入orm等框架之后可自行删除
*/
{
*/ {
ApyAccount apyAccount1 = new ApyAccount();
apyAccount1.setPayId(1);
apyAccount1.setPartner("2088102169916436");
@@ -41,7 +40,6 @@ public class ApyAccountRepository {
apyAccount1.setSeller("2088102169916436");
apyAccount1.setSignType(SignUtils.RSA.name());
apyAccount1.setPayType(PayType.aliPay);
apyAccount1.setMsgType(MsgType.text);
//设置测试环境
apyAccount1.setTest(true);
apyAccounts.put(apyAccount1.getPayId(), apyAccount1);
@@ -60,7 +58,6 @@ public class ApyAccountRepository {
apyAccount2.setSeller("1469188802");
apyAccount2.setSignType(SignUtils.MD5.name());
apyAccount2.setPayType(PayType.wxPay);
apyAccount2.setMsgType(MsgType.xml);
//设置测试环境
apyAccount2.setTest(false);
apyAccounts.put(apyAccount2.getPayId(), apyAccount2);
@@ -78,7 +75,6 @@ public class ApyAccountRepository {
apyAccount3.setInputCharset("UTF-8");
apyAccount3.setSignType(SignUtils.MD5.name());
apyAccount3.setPayType(PayType.wxPay);
apyAccount3.setMsgType(MsgType.xml);
apyAccounts.put(apyAccount3.getPayId(), apyAccount3);
ApyAccount apyAccount4 = new ApyAccount();
@@ -95,7 +91,6 @@ public class ApyAccountRepository {
apyAccount4.setInputCharset("UTF-8");
apyAccount4.setSignType(SignUtils.RSA2.name());
apyAccount4.setPayType(PayType.unionPay);
apyAccount4.setMsgType(MsgType.json);
apyAccount4.setTest(true);
apyAccounts.put(apyAccount4.getPayId(), apyAccount4);
@@ -106,7 +101,6 @@ public class ApyAccountRepository {
apyAccount5.setStorePassword("12BkDT8152Zj");//API password
apyAccount5.setInputCharset("UTF-8");
apyAccount5.setPayType(PayType.payoneer);
apyAccount5.setMsgType(MsgType.json);
apyAccount5.setTest(true);
apyAccounts.put(apyAccount5.getPayId(), apyAccount5);
@@ -116,7 +110,6 @@ public class ApyAccountRepository {
apyAccount6.setPrivateKey("1EBMIjAag6NiRdXZxteTv0amEsmKN345xJv3bN7f_HRXSqcRJlW7PXhYXjI9sk5I4nKYOHgeqzhXCXKFo");//API password
apyAccount6.setInputCharset("UTF-8");
apyAccount6.setPayType(PayType.payPal);
apyAccount6.setMsgType(MsgType.json);
apyAccount6.setTest(true);
apyAccounts.put(apyAccount6.getPayId(), apyAccount6);
}
@@ -125,10 +118,11 @@ public class ApyAccountRepository {
/**
* 根据id获取对应的账户信息
*
* @param payId 账户id
* @return 账户信息
*/
public ApyAccount findByPayId(Integer payId){
public ApyAccount findByPayId(Integer payId) {
// TODO 2016/11/18 1:23 author: egan 这里简单模拟 具体实现 略。。
return apyAccounts.get(payId);
}

View File

@@ -2,12 +2,11 @@
package com.egzosn.pay.demo.entity;
import com.egzosn.pay.common.bean.MsgType;
//import javax.persistence.*;
/**
* 支付账户
*
* @author: egan
* email egzosn@gmail.com
* date 2016/11/18 0:36
@@ -59,12 +58,9 @@ public class ApyAccount {
// @Enumerated(EnumType.STRING)
// @Column(name = "pay_type")
private PayType payType;
// 消息类型text,xml,json
// @Enumerated(EnumType.STRING)
// @Column(name = "msg_type")
private MsgType msgType;
//是否为测试环境
private boolean isTest = false;
public Integer getPayId() {
return payId;
}
@@ -145,14 +141,6 @@ public class ApyAccount {
this.payType = payType;
}
public MsgType getMsgType() {
return msgType;
}
public void setMsgType(MsgType msgType) {
this.msgType = msgType;
}
public String getInputCharset() {
return inputCharset;
}
@@ -199,7 +187,6 @@ public class ApyAccount {
", signType='" + signType + '\'' +
", inputCharset='" + inputCharset + '\'' +
", payType=" + payType +
", msgType=" + msgType +
'}';
}
}

View File

@@ -6,7 +6,6 @@ import com.egzosn.pay.ali.bean.AliTransactionType;
import com.egzosn.pay.common.api.PayService;
import com.egzosn.pay.common.bean.BasePayType;
import com.egzosn.pay.common.bean.CertStoreType;
import com.egzosn.pay.common.bean.MsgType;
import com.egzosn.pay.common.bean.TransactionType;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.demo.service.handler.WxPayMessageHandler;
@@ -30,7 +29,6 @@ import com.egzosn.pay.wx.youdian.api.WxYouDianPayService;
import com.egzosn.pay.wx.youdian.bean.YoudianTransactionType;
/**
* 支付类型
*
@@ -41,7 +39,7 @@ import com.egzosn.pay.wx.youdian.bean.YoudianTransactionType;
public enum PayType implements BasePayType {
aliPay{
aliPay {
/**
* @see com.egzosn.pay.ali.api.AliPayService
* @param apyAccount
@@ -61,7 +59,6 @@ public enum PayType implements BasePayType {
configStorage.setSignType(apyAccount.getSignType());
configStorage.setSeller(apyAccount.getSeller());
configStorage.setPayType(apyAccount.getPayType().toString());
configStorage.setMsgType(apyAccount.getMsgType());
configStorage.setInputCharset(apyAccount.getInputCharset());
configStorage.setTest(apyAccount.isTest());
//请求连接池配置
@@ -82,7 +79,7 @@ public enum PayType implements BasePayType {
}
},wxPay {
}, wxPay {
@Override
public PayService getPayService(ApyAccount apyAccount) {
WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage();
@@ -95,7 +92,6 @@ public enum PayType implements BasePayType {
wxPayConfigStorage.setReturnUrl(apyAccount.getReturnUrl());
wxPayConfigStorage.setSignType(apyAccount.getSignType());
wxPayConfigStorage.setPayType(apyAccount.getPayType().toString());
wxPayConfigStorage.setMsgType(apyAccount.getMsgType());
wxPayConfigStorage.setInputCharset(apyAccount.getInputCharset());
wxPayConfigStorage.setTest(apyAccount.isTest());
@@ -124,7 +120,7 @@ public enum PayType implements BasePayType {
return WxTransactionType.valueOf(transactionType);
}
},youdianPay {
}, youdianPay {
@Override
public PayService getPayService(ApyAccount apyAccount) {
// TODO 2017/1/23 14:12 author: egan 集群的话,友店可能会有bug。暂未测试集群环境
@@ -135,11 +131,10 @@ public enum PayType implements BasePayType {
// wxPayConfigStorage.setReturnUrl(apyAccount.getReturnUrl());
wxPayConfigStorage.setSignType(apyAccount.getSignType());
wxPayConfigStorage.setPayType(apyAccount.getPayType().toString());
wxPayConfigStorage.setMsgType(apyAccount.getMsgType());
wxPayConfigStorage.setSeller(apyAccount.getSeller());
wxPayConfigStorage.setInputCharset(apyAccount.getInputCharset());
wxPayConfigStorage.setTest(apyAccount.isTest());
return new WxYouDianPayService(wxPayConfigStorage);
return new WxYouDianPayService(wxPayConfigStorage);
}
/**
@@ -153,8 +148,7 @@ public enum PayType implements BasePayType {
return YoudianTransactionType.valueOf(transactionType);
}
},fuiou{
}, fuiou {
@Override
public PayService getPayService(ApyAccount apyAccount) {
FuiouPayConfigStorage fuiouPayConfigStorage = new FuiouPayConfigStorage();
@@ -164,7 +158,6 @@ public enum PayType implements BasePayType {
fuiouPayConfigStorage.setReturnUrl(apyAccount.getReturnUrl());
fuiouPayConfigStorage.setSignType(apyAccount.getSignType());
fuiouPayConfigStorage.setPayType(apyAccount.getPayType().toString());
fuiouPayConfigStorage.setMsgType(apyAccount.getMsgType());
fuiouPayConfigStorage.setInputCharset(apyAccount.getInputCharset());
fuiouPayConfigStorage.setTest(apyAccount.isTest());
return new FuiouPayService(fuiouPayConfigStorage);
@@ -176,8 +169,7 @@ public enum PayType implements BasePayType {
}
},unionPay{
}, unionPay {
@Override
public PayService getPayService(ApyAccount apyAccount) {
UnionPayConfigStorage unionPayConfigStorage = new UnionPayConfigStorage();
@@ -201,7 +193,6 @@ public enum PayType implements BasePayType {
unionPayConfigStorage.setReturnUrl(apyAccount.getReturnUrl());
unionPayConfigStorage.setSignType(apyAccount.getSignType());
unionPayConfigStorage.setPayType(apyAccount.getPayType().toString());
unionPayConfigStorage.setMsgType(apyAccount.getMsgType());
unionPayConfigStorage.setInputCharset(apyAccount.getInputCharset());
unionPayConfigStorage.setTest(apyAccount.isTest());
return new UnionPayService(unionPayConfigStorage);
@@ -213,13 +204,12 @@ public enum PayType implements BasePayType {
}
},payoneer{
}, payoneer {
@Override
public PayService getPayService(ApyAccount apyAccount) {
PayoneerConfigStorage configStorage = new PayoneerConfigStorage();
//设置商户Id
configStorage.setProgramId(apyAccount.getPartner());
configStorage.setMsgType(MsgType.json);
configStorage.setInputCharset("utf-8");
//"PayoneerPay 用户名"
configStorage.setUserName(apyAccount.getSeller());
@@ -243,7 +233,7 @@ public enum PayType implements BasePayType {
}
},payPal{
}, payPal {
@Override
public PayService getPayService(ApyAccount apyAccount) {
PayPalConfigStorage storage = new PayPalConfigStorage();

View File

@@ -1,22 +1,28 @@
package com.egzosn.pay.demo.service;
import javax.annotation.Resource;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import com.egzosn.pay.common.api.PayConfigStorage;
import com.egzosn.pay.common.api.PayMessageHandler;
import com.egzosn.pay.common.api.PayMessageRouter;
import com.egzosn.pay.common.api.PayService;
import com.egzosn.pay.common.bean.MsgType;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.demo.entity.ApyAccount;
import com.egzosn.pay.demo.entity.PayType;
import com.egzosn.pay.demo.service.handler.*;
import com.egzosn.pay.demo.service.handler.AliPayMessageHandler;
import com.egzosn.pay.demo.service.handler.FuiouPayMessageHandler;
import com.egzosn.pay.demo.service.handler.PayoneerMessageHandler;
import com.egzosn.pay.demo.service.handler.UnionPayMessageHandler;
import com.egzosn.pay.demo.service.handler.WxPayMessageHandler;
import com.egzosn.pay.demo.service.handler.YouDianPayMessageHandler;
import com.egzosn.pay.demo.service.interceptor.AliPayMessageInterceptor;
import com.egzosn.pay.demo.service.interceptor.YoudianPayMessageInterceptor;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import javax.annotation.Resource;
/**
* 支付响应对象
*
* @author: egan
* email egzosn@gmail.com
* date 2016/11/18 0:34
@@ -38,6 +44,7 @@ public class PayResponse {
/**
* 初始化支付配置
*
* @param apyAccount 账户信息
* @see ApyAccount 对应表结构详情--》 /pay-java-demo/resources/apy_account.sql
*/
@@ -52,13 +59,14 @@ public class PayResponse {
/**
* 获取http配置如果配置为null则为默认配置无代理,无证书的请求方式。
* 此处非必需
* 此处非必需
*
* @param apyAccount 账户信息
* @return 请求配置
*/
public HttpConfigStorage getHttpConfigStorage(ApyAccount apyAccount){
public HttpConfigStorage getHttpConfigStorage(ApyAccount apyAccount) {
HttpConfigStorage httpConfigStorage = new HttpConfigStorage();
/* 网路代理配置 根据需求进行设置*/
/* 网路代理配置 根据需求进行设置*/
// //http代理地址
// httpConfigStorage.setHttpProxyHost("192.168.1.69");
// //代理端口
@@ -77,6 +85,7 @@ public class PayResponse {
/**
* 配置路由
*
* @param payId 指定账户id用户多微信支付多支付宝支付
*/
private void buildRouter(Integer payId) {
@@ -84,7 +93,6 @@ public class PayResponse {
router
.rule()
//消息类型
.msgType(MsgType.text.name())
//支付账户事件类型
.payType(PayType.aliPay.name())
//拦截器
@@ -93,33 +101,27 @@ public class PayResponse {
.handler(spring.getBean(AliPayMessageHandler.class))
.end()
.rule()
.msgType(MsgType.xml.name())
.payType(PayType.wxPay.name())
.handler(autowire(new WxPayMessageHandler(payId)))
.end()
.rule()
.msgType(MsgType.json.name())
.payType(PayType.youdianPay.name())
.interceptor(new YoudianPayMessageInterceptor()) //拦截器
.handler(autowire(new YouDianPayMessageHandler(payId)))
.end()
.rule()
.msgType(MsgType.xml.name())
.payType(PayType.fuiou.name())
.handler(autowire(new FuiouPayMessageHandler(payId)))
.end()
.rule()
.msgType(MsgType.json.name())
.payType(PayType.unionPay.name())
.handler(autowire(new UnionPayMessageHandler(payId)))
.end()
.rule()
.msgType(MsgType.json.name())
.payType(PayType.payoneer.name())
.handler(autowire(new PayoneerMessageHandler(payId)))
.end()
.rule()
.msgType(MsgType.text.name())
.payType(PayType.payPal.name())
.handler(spring.getBean(AliPayMessageHandler.class))
.end()

View File

@@ -1,9 +1,10 @@
package com.egzosn.pay.fuiou.api;
import com.egzosn.pay.common.api.BasePayConfigStorage;
/**
* @author Actinia
* <pre>
* <pre>
* email hayesfu@qq.com
* create 2017 2017/1/16 0016
* </pre>
@@ -15,7 +16,8 @@ public class FuiouPayConfigStorage extends BasePayConfigStorage {
private String mchntCd;
/**
* 应用id
* 应用id
*
* @return 空
*/
@Override
@@ -23,21 +25,31 @@ public class FuiouPayConfigStorage extends BasePayConfigStorage {
return null;
}
/**
* 应用id
* 纠正名称
*
* @return 应用id
*/
@Override
public String getAppId() {
return null;
}
/**
* 合作商唯一标识
*
*/
@Override
public String getPid () {
public String getPid() {
return mchntCd;
}
public String getMchntCd () {
public String getMchntCd() {
return mchntCd;
}
public void setMchntCd (String mchntCd) {
public void setMchntCd(String mchntCd) {
this.mchntCd = mchntCd;
}

View File

@@ -1,7 +1,21 @@
package com.egzosn.pay.fuiou.api;
import java.io.InputStream;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.common.api.BasePayService;
import com.egzosn.pay.common.bean.*;
import com.egzosn.pay.common.bean.MethodType;
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;
@@ -12,15 +26,10 @@ import com.egzosn.pay.common.util.str.StringUtils;
import com.egzosn.pay.fuiou.bean.FuiouRefundResult;
import com.egzosn.pay.fuiou.bean.FuiouTransactionType;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
/**
* @author Actinia
* <pre>
*email hayesfu@qq.com
* <pre>
* email hayesfu@qq.com
* create 2017 2017/1/16 0016
* </pre>
*/
@@ -38,7 +47,7 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
/**
* B2C/B2B支付
*/
public static final String URL_FuiouSmpGate = "smpGate.do";
public static final String URL_FuiouSmpGate = "smpGate.do";
/**
* B2C/B2B支付(跨境支付)
*/
@@ -63,39 +72,46 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
/**
* 获取对应的请求地址
*
* @return 请求地址
*/
@Override
public String getReqUrl(TransactionType transactionType){
public String getReqUrl(TransactionType transactionType) {
return payConfigStorage.isTest() ? DEV_URL_FUIOU_BASE_DOMAIN : URL_FUIOU_BASE_DOMAIN;
}
/**
* 获取对应的请求地址
*
* @return 请求地址
*/
public String getReqUrl(){
public String getReqUrl() {
return getReqUrl(null);
}
/**
* 构造函数,初始化时候使用
*
* @param payConfigStorage 支付账户配置信息
* @param configStorage 网络代理配置
* @param configStorage 网络代理配置
*/
public FuiouPayService (FuiouPayConfigStorage payConfigStorage, HttpConfigStorage configStorage) {
public FuiouPayService(FuiouPayConfigStorage payConfigStorage, HttpConfigStorage configStorage) {
super(payConfigStorage, configStorage);
}
/**
* 构造函数,初始化时候使用
*
* @param payConfigStorage 支付账户配置信息
*/
public FuiouPayService (FuiouPayConfigStorage payConfigStorage) {
public FuiouPayService(FuiouPayConfigStorage payConfigStorage) {
super(payConfigStorage);
}
/**
* 回调校验
*
* @param params 回调回来的参数集
* @return 返回检验结果 0000 成功 其他失败
*/
@@ -108,7 +124,8 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
try {
//返回参数校验 和 重新请求订单检查数据是否合法
return (signVerify(params, (String) params.remove("md5")) && verifySource((String) params.get("order_id")));
} catch (PayErrorException e) {
}
catch (PayErrorException e) {
e.printStackTrace();
}
return false;
@@ -117,11 +134,10 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
/**
* 回调签名校验
*
* @param params 参数集
* @param responseSign 响应的签名串
* @param params 参数集
* @param responseSign 响应的签名串
* @return 校验结果
*/
@Override
public boolean signVerify(Map<String, Object> params, String responseSign) {
String sign = createSign(SignUtils.parameters2MD5Str(params, "|"), payConfigStorage.getInputCharset());
@@ -135,14 +151,13 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
* @param orderId 业务id, 数据的真实性.
* @return 返回校验结果
*/
@Override
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);
params.put("md5", createSign(SignUtils.parameters2MD5Str(params, "|"), payConfigStorage.getInputCharset()));
JSONObject resultJson = getHttpRequestTemplate().postForObject(getReqUrl() + URL_FuiouSmpAQueryGate + "?" + UriVariables.getMapToParameters(params), null, JSONObject.class);
if (null == resultJson){
if (null == resultJson) {
return false;
}
return "0000".equals(resultJson.getJSONObject("plain").getString("order_pay_code"));
@@ -151,12 +166,13 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
/**
* 将支付请求参数加密成md5
*
* @param order 支付订单
* @return 返回支付请求参数集合
*/
@Override
public Map<String, Object> orderInfo(PayOrder order) {
if (null == order.getTransactionType()){
if (null == order.getTransactionType()) {
order.setTransactionType(FuiouTransactionType.B2C);
}
@@ -168,6 +184,7 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
/**
* 按序添加请求参数
*
* @param order 支付订单
* @return 返回支付请求参数集合
*/
@@ -189,9 +206,10 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
//商户接受的支付结果后台通知地址 //非必填
parameters.put("back_notify_url", StringUtils.isBlank(payConfigStorage.getNotifyUrl()) ? "" : payConfigStorage.getNotifyUrl());
if (null != order.getExpirationTime()){
if (null != order.getExpirationTime()) {
parameters.put("order_valid_time", DateUtils.minutesRemaining(order.getExpirationTime()) + "m");
}else {
}
else {
//超时时间 1m-15天m分钟、h小时、d天、1c当天有效
parameters.put("order_valid_time", "30m");
}
@@ -210,6 +228,7 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
/**
* 对内容进行加密
*
* @param content 需要加密的内容
* @param characterEncoding 字符编码
* @return 加密后的字符串
@@ -221,45 +240,48 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
/**
* 将请求参数或者请求流转化为 Map
*
* @param parameterMap 请求参数
* @param is 请求流
* @return 返回参数集合
*/
@Override
public Map<String, Object> getParameter2Map(Map<String, String[]> parameterMap, InputStream is) {
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");
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
* 将parameterMap对应的key存放至params
*
* @param parameterMap 请求参数
* @param params 转化的对象
* @param key 需要取值的key
* @param params 转化的对象
* @param key 需要取值的key
* @return params
*/
public Map<String, Object> conversion(Map<String, String[]> parameterMap, Map<String, Object> params ,String key){
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] + ",";
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 code 返回代码
* @param message 返回信息
* @return 消息实体
*/
@@ -268,9 +290,11 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
public PayOutMessage getPayOutMessage(String code, String message) {
return PayOutMessage.TEXT().content(code.toLowerCase()).build();
}
/**
* 获取成功输出消息,用户返回给支付端
* 主要用于拦截器中返回
*
* @param payMessage 支付回调消息
* @return 返回输出消息
*/
@@ -281,6 +305,7 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
/**
* 发送支付请求form表单
*
* @param orderInfo 发起支付的订单信息
* @param method 请求方式 "post" "get",
* @return form表单提交的html字符串
@@ -288,22 +313,24 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
@Override
public String buildRequest(Map<String, Object> orderInfo, MethodType method) {
return getFormString(orderInfo, method,getReqUrl() + URL_FuiouSmpGate );
return getFormString(orderInfo, method, getReqUrl() + URL_FuiouSmpGate);
}
/**
* 获取输出二维码,用户返回给支付端,
* 暂未实现或无此功能
*
* @param order 发起支付的订单信息
* @return 空
*/
@Override
public String getQrPay (PayOrder order) {
public String getQrPay(PayOrder order) {
throw new UnsupportedOperationException();
}
/**
* 暂未实现或无此功能
*
* @param order 发起支付的订单信息
* @return 不支持的操作异常
*/
@@ -314,20 +341,21 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
/**
* 根据参数形成form表单
* @param param 参数
*
* @param param 参数
* @param method 请求方式 get_post
* @param url 支付请求url地址
* @param url 支付请求url地址
* @return form表单html代码
*/
private String getFormString(Map<String, Object> param, MethodType method,String url) {
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\">");
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();
@@ -341,6 +369,7 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
/**
* 交易查询接口
*
* @param tradeNo 支付平台订单号
* @param outTradeNo 商户单号
* @return 空
@@ -357,9 +386,9 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
}
/**
* 交易关闭接口
*
* @param tradeNo 支付平台订单号
* @param outTradeNo 商户单号
* @return 空
@@ -370,13 +399,10 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
}
/**
* 申请退款接口
*
* @param refundOrder 退款订单信息
* @param refundOrder 退款订单信息
* @return 退款返回结果集
*/
@Override
@@ -413,6 +439,7 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
/**
* 下载对账单
*
* @param billDate 账单时间日账单格式为yyyy-MM-dd月账单格式为yyyy-MM。
* @param billType 账单类型商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型trade、signcustomertrade指商户基于支付宝交易收单的业务账单signcustomer是指基于商户支付宝余额收入及支出等资金变动的帐务账单
* @return 空
@@ -422,19 +449,5 @@ public class FuiouPayService extends BasePayService<FuiouPayConfigStorage> {
return Collections.emptyMap();
}
/**
* @param tradeNoOrBillDate 支付平台订单号或者账单类型, 具体请
* 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link PayErrorException}
* @param outTradeNoBillType 商户单号或者 账单类型
* @param transactionType 交易类型
*
* @return 返回支付方对应接口的结果
*/
@Override
public Map<String, Object> secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType) {
return Collections.emptyMap();
}
}

View File

@@ -1,10 +1,12 @@
package com.egzosn.pay.payoneer.api;
import com.egzosn.pay.common.api.BasePayConfigStorage;
/**
* Payoneer P卡 支付 配置
*
* @author Actinia
* @author egan
* @author egan
* <pre>
* email hayesfu@qq.com
* date 2018-01-19
@@ -16,27 +18,38 @@ public class PayoneerConfigStorage extends BasePayConfigStorage {
*/
private String programId;
/**
* PayoneerPay 用户名
* PayoneerPay 用户名
*/
private String userName;
/**
* 应用id
* 应用id
*
* @return 空
*/
@Override
@Deprecated
public String getAppid() {
return null;
}
/**
* 应用id
* 纠正名称
*
* @return 应用id
*/
@Override
public String getAppId() {
return null;
}
/**
* 合作商唯一标识
*
*/
@Override
public String getPid () {
public String getPid() {
return programId;
}
@@ -46,7 +59,8 @@ public class PayoneerConfigStorage extends BasePayConfigStorage {
}
/**
* 获取商户Id
* 获取商户Id
*
* @return 商户Id
*/
public String getProgramId() {
@@ -54,7 +68,8 @@ public class PayoneerConfigStorage extends BasePayConfigStorage {
}
/**
* 设置商户Id
* 设置商户Id
*
* @param programId 商户Id
*/
public void setProgramId(String programId) {
@@ -62,10 +77,11 @@ public class PayoneerConfigStorage extends BasePayConfigStorage {
}
/**
* PayoneerPay 用户名
* PayoneerPay 用户名
*
* @param userName 用户名
*/
public void setUserName(String userName){
public void setUserName(String userName) {
this.userName = userName;
}
@@ -74,16 +90,18 @@ public class PayoneerConfigStorage extends BasePayConfigStorage {
}
/**
* 设置PayoneerPay API password
* 设置PayoneerPay API password
*
* @param apiPassword api密钥
*/
public void setApiPassword(String apiPassword){
public void setApiPassword(String apiPassword) {
setKeyPrivate(apiPassword);
}
/**
* 获取 PayoneerPay API password
* 获取 PayoneerPay API password
*/
public String getApiPassword(){
return getKeyPrivate();
public String getApiPassword() {
return getKeyPrivate();
}
}

View File

@@ -1,9 +1,31 @@
package com.egzosn.pay.payoneer.api;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.http.Header;
import org.apache.http.entity.ContentType;
import org.apache.http.message.BasicHeader;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.common.api.BasePayService;
import com.egzosn.pay.common.bean.*;
import com.egzosn.pay.common.bean.BaseRefundResult;
import com.egzosn.pay.common.bean.CurType;
import com.egzosn.pay.common.bean.DefaultCurType;
import com.egzosn.pay.common.bean.MethodType;
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.bean.TransferOrder;
import com.egzosn.pay.common.bean.outbuilder.PayTextOutMessage;
import com.egzosn.pay.common.bean.result.PayException;
import com.egzosn.pay.common.exception.PayErrorException;
@@ -14,19 +36,13 @@ 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.payoneer.bean.PayoneerTransactionType;
import org.apache.http.Header;
import org.apache.http.entity.ContentType;
import org.apache.http.message.BasicHeader;
import java.math.BigDecimal;
import java.util.*;
/**
* payoneer业务逻辑
*
* @author Actinia
* @author egan
* <pre>
* <pre>
* email: egzosn@gmail.com
* email: hayesfu@qq.com
* create 2018-01-19
@@ -61,20 +77,21 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
/**
* 获取授权请求头
*
* @return 授权请求头
*/
private HttpHeader authHeader(){
private HttpHeader authHeader() {
List<Header> headers = new ArrayList<>();
headers.add(new BasicHeader("Authorization", "Basic " + authorizationString(getPayConfigStorage().getSeller(), getPayConfigStorage().getKeyPrivate())));
headers.add(new BasicHeader("Authorization", "Basic " + authorizationString(getPayConfigStorage().getSeller(), getPayConfigStorage().getKeyPrivate())));
return new HttpHeader(headers);
}
/**
* 获取授权页面
*
* @param payeeId 收款id
*
* @return 返回请求结果
*/
@Override
@@ -97,7 +114,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
* 授权状态
*
* @param payeeId 用户id
*
* @return 返回是否认证 true 已认证
*/
@Override
@@ -110,7 +126,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
* 获取授权用户信息
*
* @param payeeId 用户id
*
* @return 获取授权用户信息,包含用户状态,注册时间,联系人信息,地址信息等等
*/
@Override
@@ -123,7 +138,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
* 回调校验
*
* @param params 回调回来的参数集
*
* @return 签名校验 true通过
*/
@Override
@@ -137,28 +151,14 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
return false;
}
/**
* 签名校验
*
* @param params 参数集
* @param sign 签名原文
*
* @return 签名校验 true通过
*/
@Override
public boolean signVerify(Map<String, Object> params, String sign) {
return true;
}
/**
* 支付宝需要,微信是否也需要再次校验来源,进行订单查询
* 校验数据来源
*
* @param outTradeNo 业务id, 数据的真实性.
*
* @return true通过
*/
@Override
public boolean verifySource(String outTradeNo) {
Map<String, Object> data = query(null, outTradeNo);
return "DONE".equals(data.get("status"));
@@ -168,7 +168,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
* 返回创建的订单信息
*
* @param order 支付订单
*
* @return 订单信息
* @see PayOrder 支付订单信息
*/
@@ -192,7 +191,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
*
* @param content 需要签名的内容
* @param characterEncoding 字符编码
*
* @return 签名
*/
@Override
@@ -206,7 +204,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
*
* @param code 状态
* @param message 消息
*
* @return 返回输出消息
*/
@Override
@@ -219,7 +216,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
* 主要用于拦截器中返回
*
* @param payMessage 支付回调消息
*
* @return 返回输出消息
*/
@Override
@@ -232,7 +228,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
*
* @param orderInfo 发起支付的订单信息
* @param method 请求方式 "post" "get",
*
* @return 获取输出消息,用户返回给支付端, 针对于web端
* @see MethodType 请求类型
*/
@@ -245,7 +240,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
* 获取输出二维码,用户返回给支付端,
*
* @param order 发起支付的订单信息
*
* @return 返回图片信息,支付时需要的
*/
@Override
@@ -257,7 +251,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
* 刷卡付,pos主动扫码付款(条码付)
*
* @param order 发起支付的订单信息
*
* @return 返回支付结果
*/
@Override
@@ -271,7 +264,7 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
if (response != null) {
return response;
}
throw new PayErrorException(new PayException("fail", "Payoneer申请收款失败,原因:未有返回值" ));
throw new PayErrorException(new PayException("fail", "Payoneer申请收款失败,原因:未有返回值"));
}
/**
@@ -279,7 +272,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
*
* @param tradeNo 支付平台订单号
* @param outTradeNo 商户单号
*
* @return 返回查询回来的结果集,支付方原值返回
*/
@Override
@@ -293,7 +285,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
*
* @param tradeNo 支付平台订单号
* @param outTradeNo 商户单号
*
* @return 返回支付方交易关闭后的结果
*/
@Override
@@ -314,13 +305,10 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
}
/**
* 申请退款接口
*
* @param refundOrder 退款订单信息
*
* @return 返回支付方申请退款后的结果
*/
@Override
@@ -390,7 +378,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
*
* @param billDate 账单时间日账单格式为yyyy-MM-dd月账单格式为yyyy-MM。
* @param billType 账单类型商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型trade、signcustomertrade指商户基于支付宝交易收单的业务账单signcustomer是指基于商户支付宝余额收入及支出等资金变动的帐务账单
*
* @return 返回支付方下载对账单的结果
*/
@Override
@@ -404,18 +391,17 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
* 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link PayErrorException}
* @param outTradeNoBillType 商户单号或者 账单类型
* @param transactionType 交易类型
*
* @return 返回支付方对应接口的结果
*/
@Override
public Map<String, Object> secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType) {
MethodType methodType = null;
if (transactionType == PayoneerTransactionType.CHARGE_CANCEL) { // 退款
methodType = MethodType.POST;
}else {
}
else {
methodType = MethodType.GET;
}
JSONObject result = getHttpRequestTemplate().doExecute(UriVariables.getUri(getReqUrl(transactionType), outTradeNoBillType), authHeader() ,JSONObject.class, methodType);
JSONObject result = getHttpRequestTemplate().doExecute(UriVariables.getUri(getReqUrl(transactionType), outTradeNoBillType), authHeader(), JSONObject.class, methodType);
return result;
}
@@ -423,7 +409,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
* 转账
*
* @param order 转账订单
*
* @return 对应的转账结果
*/
@Override
@@ -449,7 +434,6 @@ public class PayoneerPayService extends BasePayService<PayoneerConfigStorage> im
*
* @param outNo 商户转账订单号
* @param tradeNo 支付平台转账订单号
*
* @return 对应的转账订单
*/
@Override

View File

@@ -8,37 +8,58 @@ import com.egzosn.pay.common.api.BasePayConfigStorage;
* 贝宝支付配置存储
*
* @author egan
* <p>
* email egzosn@gmail.com
* date 2018-4-8 22:11:42
* <p>
* email egzosn@gmail.com
* date 2018-4-8 22:11:42
*/
public class PayPalConfigStorage extends BasePayConfigStorage {
private String clientID;
private String clientId;
@Override
@Deprecated
public String getAppid() {
return clientID;
return clientId;
}
/**
* 应用id
* 纠正名称
*
* @return 应用id
*/
@Override
public String getAppId() {
return clientId;
}
@Override
public String getPid() {
return clientID;
return clientId;
}
@Override
public String getSeller() {
return clientID;
return clientId;
}
public String getClientID() {
return clientID;
return clientId;
}
public void setClientID(String clientID) {
this.clientID = clientID;
public void setClientID(String clientId) {
this.clientId = clientId;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getClientSecret() {
return getKeyPrivate();
}
@@ -50,6 +71,10 @@ public class PayPalConfigStorage extends BasePayConfigStorage {
/**
* 设置取消页面的url
* <pre>
* 注意:这里不是异步回调的通知
* IPN 地址设置的路径https://developer.paypal.com/developer/ipnSimulator/
* </pre>
*
* @param cancelUrl 取消页面的url
*/
@@ -59,6 +84,11 @@ public class PayPalConfigStorage extends BasePayConfigStorage {
/**
* 获取取消页面的url
* <pre>
* 注意:这里不是异步回调的通知
* IPN 地址设置的路径https://developer.paypal.com/developer/ipnSimulator/
* </pre>
*
* @return 取消页面的url
*/
public String getCancelUrl() {

View File

@@ -1,10 +1,34 @@
package com.egzosn.pay.paypal.api;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import org.apache.http.Header;
import org.apache.http.entity.ContentType;
import org.apache.http.message.BasicHeader;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.common.api.BasePayService;
import com.egzosn.pay.common.bean.*;
import com.egzosn.pay.common.bean.BaseRefundResult;
import com.egzosn.pay.common.bean.CurType;
import com.egzosn.pay.common.bean.DefaultCurType;
import com.egzosn.pay.common.bean.MethodType;
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.bean.result.PayException;
import com.egzosn.pay.common.exception.PayErrorException;
import com.egzosn.pay.common.http.HttpHeader;
@@ -12,24 +36,22 @@ import com.egzosn.pay.common.http.HttpStringEntity;
import com.egzosn.pay.common.util.Util;
import com.egzosn.pay.common.util.str.StringUtils;
import com.egzosn.pay.paypal.bean.PayPalTransactionType;
import com.egzosn.pay.paypal.bean.order.*;
import org.apache.http.Header;
import org.apache.http.entity.ContentType;
import org.apache.http.message.BasicHeader;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.locks.Lock;
import com.egzosn.pay.paypal.bean.order.Amount;
import com.egzosn.pay.paypal.bean.order.Links;
import com.egzosn.pay.paypal.bean.order.Payer;
import com.egzosn.pay.paypal.bean.order.Payment;
import com.egzosn.pay.paypal.bean.order.RedirectUrls;
import com.egzosn.pay.paypal.bean.order.Transaction;
/**
* 贝宝支付配置存储
* @author egan
*
* @author egan
* <p>
* email egzosn@gmail.com
* date 2018-4-8 22:15:09
*/
public class PayPalPayService extends BasePayService<PayPalConfigStorage>{
public class PayPalPayService extends BasePayService<PayPalConfigStorage> {
/**
* 沙箱环境
@@ -42,10 +64,11 @@ public class PayPalPayService extends BasePayService<PayPalConfigStorage>{
/**
* 获取对应的请求地址
*
* @return 请求地址
*/
@Override
public String getReqUrl(TransactionType transactionType){
public String getReqUrl(TransactionType transactionType) {
return (payConfigStorage.isTest() ? SANDBOX_REQ_URL : REQ_URL) + transactionType.getMethod();
}
@@ -55,21 +78,23 @@ public class PayPalPayService extends BasePayService<PayPalConfigStorage>{
}
/**
* 获取请求token
*
* @return 授权令牌
*/
public String getAccessToken() {
public String getAccessToken() {
try {
return getAccessToken(false);
} catch (PayErrorException e) {
}
catch (PayErrorException e) {
throw e;
}
}
/**
* 获取授权令牌
* 获取授权令牌
*
* @param forceRefresh 是否重新获取, true重新获取
* @return 新的授权令牌
* @throws PayErrorException 支付异常
@@ -84,21 +109,23 @@ public class PayPalPayService extends BasePayService<PayPalConfigStorage>{
}
if (payConfigStorage.isAccessTokenExpired()) {
Map<String, String> header = new HashMap<>();
header.put("Authorization", "Basic " + authorizationString(getPayConfigStorage().getAppid(), getPayConfigStorage().getKeyPrivate()));
header.put("Accept", "application/json");
header.put("Content-Type", "application/x-www-form-urlencoded");
try {
HttpStringEntity entity = new HttpStringEntity("grant_type=client_credentials", header);
JSONObject resp = getHttpRequestTemplate().postForObject(getReqUrl(PayPalTransactionType.AUTHORIZE), entity, JSONObject.class);
payConfigStorage.updateAccessToken(String.format("%s %s", resp.getString("token_type" ), resp.getString("access_token" )), resp.getIntValue("expires_in" ));
Map<String, String> header = new HashMap<>();
header.put("Authorization", "Basic " + authorizationString(getPayConfigStorage().getAppid(), getPayConfigStorage().getKeyPrivate()));
header.put("Accept", "application/json");
header.put("Content-Type", "application/x-www-form-urlencoded");
try {
HttpStringEntity entity = new HttpStringEntity("grant_type=client_credentials", header);
JSONObject resp = getHttpRequestTemplate().postForObject(getReqUrl(PayPalTransactionType.AUTHORIZE), entity, JSONObject.class);
payConfigStorage.updateAccessToken(String.format("%s %s", resp.getString("token_type"), resp.getString("access_token")), resp.getIntValue("expires_in"));
} catch (UnsupportedEncodingException e) {
throw new PayErrorException(new PayException("failure", e.getMessage()));
}
}
catch (UnsupportedEncodingException e) {
throw new PayErrorException(new PayException("failure", e.getMessage()));
}
return payConfigStorage.getAccessToken();
}
} finally {
}
finally {
lock.unlock();
}
return payConfigStorage.getAccessToken();
@@ -108,28 +135,19 @@ public class PayPalPayService extends BasePayService<PayPalConfigStorage>{
@Override
public boolean verify(Map<String, Object> params) {
HttpStringEntity httpEntity = new HttpStringEntity("{\"payer_id\":\""+(String)params.get("PayerID")+"\"}", ContentType.APPLICATION_JSON);
HttpStringEntity httpEntity = new HttpStringEntity("{\"payer_id\":\"" + (String) params.get("PayerID") + "\"}", ContentType.APPLICATION_JSON);
httpEntity.setHeaders(authHeader());
JSONObject resp = getHttpRequestTemplate().postForObject(getReqUrl(PayPalTransactionType.EXECUTE), httpEntity, JSONObject.class, (String) params.get("paymentId"));
return "approved".equals(resp.getString("state"));
return "approved".equals(resp.getString("state"));
}
@Override
public boolean signVerify(Map<String, Object> params, String sign) {
return true;
}
@Override
public boolean verifySource(String id) {
return true;
}
/**
* 获取授权请求头
*
* @return 授权请求头
*/
private HttpHeader authHeader(){
private HttpHeader authHeader() {
List<Header> headers = new ArrayList<>();
headers.add(new BasicHeader("Authorization", getAccessToken()));
@@ -137,6 +155,7 @@ public class PayPalPayService extends BasePayService<PayPalConfigStorage>{
return new HttpHeader(headers);
}
/**
* 返回创建的订单信息
*
@@ -146,21 +165,22 @@ public class PayPalPayService extends BasePayService<PayPalConfigStorage>{
*/
@Override
public Map<String, Object> orderInfo(PayOrder order) {
if (null == order.getTransactionType()){
if (null == order.getTransactionType()) {
order.setTransactionType(PayPalTransactionType.sale);
}
Amount amount = new Amount();
if (null == order.getCurType()){
if (null == order.getCurType()) {
order.setCurType(DefaultCurType.USD);
}
amount.setCurrency(order.getCurType().getType());
amount.setTotal(Util.conversionAmount(order.getPrice()).toString());
Transaction transaction = new Transaction();
if (!StringUtils.isEmpty(order.getSubject())){
if (!StringUtils.isEmpty(order.getSubject())) {
transaction.setDescription(order.getSubject());
}else {
}
else {
transaction.setDescription(order.getBody());
}
transaction.setAmount(amount);
@@ -181,11 +201,11 @@ public class PayPalPayService extends BasePayService<PayPalConfigStorage>{
//发起付款后的页面转跳地址
redirectUrls.setReturnUrl(payConfigStorage.getReturnUrl());
payment.setRedirectUrls(redirectUrls);
HttpStringEntity entity = new HttpStringEntity(JSON.toJSONString(payment), ContentType.APPLICATION_JSON);
HttpStringEntity entity = new HttpStringEntity(JSON.toJSONString(payment), ContentType.APPLICATION_JSON);
entity.setHeaders(authHeader());
JSONObject resp = getHttpRequestTemplate().postForObject(getReqUrl(order.getTransactionType()), entity, JSONObject.class);
if ("created".equals(resp.getString("state")) && StringUtils.isNotEmpty(resp.getString("id"))){
order.setOutTradeNo(resp.getString("id"));
if ("created".equals(resp.getString("state")) && StringUtils.isNotEmpty(resp.getString("id"))) {
order.setTradeNo(resp.getString("id"));
}
return preOrderHandler(resp, order);
}
@@ -202,15 +222,15 @@ public class PayPalPayService extends BasePayService<PayPalConfigStorage>{
@Override
public String buildRequest(Map<String, Object> orderInfo, MethodType method) {
if (orderInfo instanceof JSONObject){
if (orderInfo instanceof JSONObject) {
Payment payment = ((JSONObject) orderInfo).toJavaObject(Payment.class);
for(Links links : payment.getLinks()){
if(links.getRel().equals("approval_url")){
return String.format("<script type=\"text/javascript\">location.href=\"%s\"</script>",links.getHref() );
for (Links links : payment.getLinks()) {
if (links.getRel().equals("approval_url")) {
return String.format("<script type=\"text/javascript\">location.href=\"%s\"</script>", links.getHref());
}
}
}
return "<script type=\"text/javascript\">location.href=\"/\"</script>" ;
return "<script type=\"text/javascript\">location.href=\"/\"</script>";
}
@Override
@@ -222,6 +242,7 @@ public class PayPalPayService extends BasePayService<PayPalConfigStorage>{
public Map<String, Object> microPay(PayOrder order) {
return null;
}
/**
* 交易查询接口
*
@@ -241,20 +262,19 @@ public class PayPalPayService extends BasePayService<PayPalConfigStorage>{
}
/**
* 申请退款接口
*
* @param refundOrder 退款订单信息
* @param refundOrder 退款订单信息
* @return 返回支付方申请退款后的结果
*/
@Override
public RefundResult refund(RefundOrder refundOrder) {
JSONObject request = new JSONObject();
JSONObject request = new JSONObject();
if (null != refundOrder.getRefundAmount() && BigDecimal.ZERO.compareTo( refundOrder.getRefundAmount()) == -1){
if (null != refundOrder.getRefundAmount() && BigDecimal.ZERO.compareTo(refundOrder.getRefundAmount()) == -1) {
Amount amount = new Amount();
if(null == refundOrder.getCurType()){
if (null == refundOrder.getCurType()) {
refundOrder.setCurType(DefaultCurType.USD);
}
@@ -266,7 +286,7 @@ public class PayPalPayService extends BasePayService<PayPalConfigStorage>{
HttpStringEntity httpEntity = new HttpStringEntity(request.toJSONString(), ContentType.APPLICATION_JSON);
httpEntity.setHeaders(authHeader());
JSONObject resp = getHttpRequestTemplate().postForObject(getReqUrl(PayPalTransactionType.REFUND), httpEntity, JSONObject.class, refundOrder.getTradeNo());
JSONObject resp = getHttpRequestTemplate().postForObject(getReqUrl(PayPalTransactionType.REFUND), httpEntity, JSONObject.class, refundOrder.getTradeNo());
return new BaseRefundResult(resp) {
@Override
public String getCode() {
@@ -332,10 +352,5 @@ public class PayPalPayService extends BasePayService<PayPalConfigStorage>{
return Collections.emptyMap();
}
@Override
public Map<String, Object> secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType) {
return Collections.emptyMap();
}
}

View File

@@ -1,16 +1,16 @@
package com.egzosn.pay.union.api;
import com.egzosn.pay.common.api.BasePayConfigStorage;
import com.egzosn.pay.common.bean.CertStoreType;
import java.io.IOException;
import java.io.InputStream;
import com.egzosn.pay.common.api.BasePayConfigStorage;
import com.egzosn.pay.common.bean.CertStoreType;
/**
* @author Actinia
* <p>
* <pre>
* <p>
* <pre>
* email hayesfu@qq.com
* create 2017 2017/11/4 0004
* </pre>
@@ -64,17 +64,18 @@ public class UnionPayConfigStorage extends BasePayConfigStorage {
* 设置私钥证书
*
* @param certificate 私钥证书地址 或者证书内容字符串
* 私钥证书密码 {@link #setKeyPrivateCertPwd(String)}
* 私钥证书密码 {@link #setKeyPrivateCertPwd(String)}
*/
public void setKeyPrivateCert(String certificate) {
super.setKeyPrivate(certificate);
this.keyPrivateCert = certificate;
}
/**
* 设置私钥证书
*
* @param keyPrivateCert 私钥证书信息流
* 私钥证书密码 {@link #setKeyPrivateCertPwd(String)}
* 私钥证书密码 {@link #setKeyPrivateCertPwd(String)}
*/
public void setKeyPrivateCert(InputStream keyPrivateCert) {
this.keyPrivateCert = keyPrivateCert;
@@ -92,6 +93,7 @@ public class UnionPayConfigStorage extends BasePayConfigStorage {
public void setAcpMiddleCert(String acpMiddleCert) {
this.acpMiddleCert = acpMiddleCert;
}
/**
* 设置中级证书
*
@@ -109,6 +111,7 @@ public class UnionPayConfigStorage extends BasePayConfigStorage {
public void setAcpRootCert(String acpRootCert) {
this.acpRootCert = acpRootCert;
}
/**
* 设置根证书
*
@@ -125,6 +128,7 @@ public class UnionPayConfigStorage extends BasePayConfigStorage {
public String getAcpRootCert() {
return (String) acpRootCert;
}
public InputStream getAcpMiddleCertInputStream() throws IOException {
return certStoreType.getInputStream(acpMiddleCert);
}
@@ -135,6 +139,7 @@ public class UnionPayConfigStorage extends BasePayConfigStorage {
/**
* 获取私钥证书密码
*
* @return 私钥证书密码
*/
public String getKeyPrivateCertPwd() {
@@ -144,11 +149,23 @@ public class UnionPayConfigStorage extends BasePayConfigStorage {
public void setKeyPrivateCertPwd(String keyPrivateCertPwd) {
this.keyPrivateCertPwd = keyPrivateCertPwd;
}
@Override
public String getAppid() {
return null;
}
/**
* 应用id
* 纠正名称
*
* @return 应用id
*/
@Override
public String getAppId() {
return null;
}
/**
* @return 合作者id
* @see #getPid()
@@ -214,6 +231,7 @@ public class UnionPayConfigStorage extends BasePayConfigStorage {
/**
* 证书存储类型
*
* @return 证书存储类型
*/
public CertStoreType getCertStoreType() {

View File

@@ -1,8 +1,37 @@
package com.egzosn.pay.union.api;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.security.GeneralSecurityException;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertStore;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.common.api.BasePayService;
import com.egzosn.pay.common.bean.*;
import com.egzosn.pay.common.bean.MethodType;
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.TransactionType;
import com.egzosn.pay.common.bean.outbuilder.PayTextOutMessage;
import com.egzosn.pay.common.bean.result.PayException;
import com.egzosn.pay.common.exception.PayErrorException;
@@ -20,19 +49,6 @@ import com.egzosn.pay.union.bean.UnionPayMessage;
import com.egzosn.pay.union.bean.UnionRefundResult;
import com.egzosn.pay.union.bean.UnionTransactionType;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.*;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @author Actinia
* <pre>
@@ -95,7 +111,8 @@ public class UnionPayService extends BasePayService<UnionPayConfigStorage> {
certDescriptor.initPrivateSignCert(payConfigStorage.getKeyPrivateCertInputStream(), payConfigStorage.getKeyPrivateCertPwd(), "PKCS12");
certDescriptor.initPublicCert(payConfigStorage.getAcpMiddleCertInputStream());
certDescriptor.initRootCert(payConfigStorage.getAcpRootCertInputStream());
} catch (IOException e) {
}
catch (IOException e) {
LOG.error(e);
}
@@ -192,7 +209,6 @@ public class UnionPayService extends BasePayService<UnionPayConfigStorage> {
* @param sign 签名原文
* @return 签名校验 true通过
*/
@Override
public boolean signVerify(Map<String, Object> params, String sign) {
SignUtils signUtils = SignUtils.valueOf(payConfigStorage.getSignType());
@@ -214,17 +230,6 @@ public class UnionPayService extends BasePayService<UnionPayConfigStorage> {
}
}
/**
* 支付宝需要,微信是否也需要再次校验来源,进行订单查询
* 校验数据来源
*
* @param id 业务id, 数据的真实性.
* @return true通过
*/
@Override
public boolean verifySource(String id) {
return false;
}
/**
* 订单超时时间。
@@ -371,11 +376,14 @@ public class UnionPayService extends BasePayService<UnionPayConfigStorage> {
/*PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult)*/
builder.build(pkixParams);
return cert;
} catch (java.security.cert.CertPathBuilderException e) {
}
catch (java.security.cert.CertPathBuilderException e) {
LOG.error("verify certificate chain fail.", e);
} catch (CertificateExpiredException e) {
}
catch (CertificateExpiredException e) {
LOG.error(e);
} catch (GeneralSecurityException e) {
}
catch (GeneralSecurityException e) {
LOG.error(e);
}
return null;
@@ -403,7 +411,8 @@ public class UnionPayService extends BasePayService<UnionPayConfigStorage> {
if (null == order.getTransactionType()) {
order.setTransactionType(UnionTransactionType.WEB);
} else if (UnionTransactionType.WEB != order.getTransactionType() && UnionTransactionType.WAP != order.getTransactionType() && UnionTransactionType.B2B != order.getTransactionType()) {
}
else if (UnionTransactionType.WEB != order.getTransactionType() && UnionTransactionType.WAP != order.getTransactionType() && UnionTransactionType.B2B != order.getTransactionType()) {
throw new PayErrorException(new PayException("-1", "错误的交易类型:" + order.getTransactionType()));
}
@@ -456,7 +465,8 @@ public class UnionPayService extends BasePayService<UnionPayConfigStorage> {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream tIn = new ByteArrayInputStream(x509CertString.getBytes("ISO-8859-1"));
x509Cert = (X509Certificate) cf.generateCertificate(tIn);
} catch (Exception e) {
}
catch (Exception e) {
throw new PayErrorException(new PayException("证书加载失败", "gen certificate error:" + e.getLocalizedMessage()));
}
return x509Cert;
@@ -675,19 +685,6 @@ public class UnionPayService extends BasePayService<UnionPayConfigStorage> {
}
/**
* @param tradeNoOrBillDate 支付平台订单号或者账单类型, 具体请
* 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link PayErrorException}
* @param outTradeNoBillType 商户单号或者 账单类型
* @param transactionType 交易类型
* @return 返回支付方对应接口的结果
*/
@Override
public Map<String, Object> secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType) {
return Collections.emptyMap();
}
/**
* 创建消息
*

View File

@@ -26,6 +26,17 @@ public class WxYouDianPayConfigStorage extends BasePayConfigStorage {
return null;
}
/**
* 应用id
* 纠正名称
*
* @return 应用id
*/
@Override
public String getAppId() {
return null;
}
@Override
public String getPid() {

View File

@@ -1,9 +1,26 @@
package com.egzosn.pay.wx.youdian.api;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.locks.Lock;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.common.api.BasePayService;
import com.egzosn.pay.common.bean.*;
import com.egzosn.pay.common.bean.BaseRefundResult;
import com.egzosn.pay.common.bean.CurType;
import com.egzosn.pay.common.bean.MethodType;
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.bean.result.PayError;
import com.egzosn.pay.common.exception.PayErrorException;
import com.egzosn.pay.common.http.HttpConfigStorage;
@@ -14,15 +31,11 @@ import com.egzosn.pay.wx.youdian.bean.WxYoudianPayMessage;
import com.egzosn.pay.wx.youdian.bean.YdPayError;
import com.egzosn.pay.wx.youdian.bean.YoudianTransactionType;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.locks.Lock;
/**
* 友店支付服务
* @author egan
* 友店支付服务
*
* @author egan
* <p>
* email egzosn@gmail.com
* date 2017/01/12 22:58
*/
@@ -33,18 +46,21 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
/**
* 获取请求token
*
* @return 授权令牌
*/
public String getAccessToken() {
public String getAccessToken() {
try {
return getAccessToken(false);
} catch (PayErrorException e) {
}
catch (PayErrorException e) {
throw e;
}
}
/**
* 获取授权令牌
* 获取授权令牌
*
* @param forceRefresh 是否重新获取, true重新获取
* @return 新的授权令牌
* @throws PayErrorException 支付异常
@@ -59,7 +75,7 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
}
if (payConfigStorage.isAccessTokenExpired()) {
if (null == payConfigStorage.getAccessToken()){
if (null == payConfigStorage.getAccessToken()) {
login();
return payConfigStorage.getAccessToken();
}
@@ -67,15 +83,17 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
StringBuilder param = new StringBuilder().append("access_token=").append(payConfigStorage.getAccessToken());
String sign = createSign(param.toString() + apbNonce, payConfigStorage.getInputCharset());
param.append("&apb_nonce=").append(apbNonce).append("&sign=").append(sign);
JSONObject json = execute(getReqUrl(YoudianTransactionType.RESET_LOGIN) + "?" + param.toString(), MethodType.GET, null );
JSONObject json = execute(getReqUrl(YoudianTransactionType.RESET_LOGIN) + "?" + param.toString(), MethodType.GET, null);
int errorcode = json.getIntValue("errorcode");
if (0 == errorcode){
if (0 == errorcode) {
payConfigStorage.updateAccessToken(payConfigStorage.getAccessToken(), 7200);
}else {
throw new PayErrorException(new YdPayError(errorcode, json.getString("msg"), json.toJSONString()));
}
else {
throw new PayErrorException(new YdPayError(errorcode, json.getString("msg"), json.toJSONString()));
}
}
} finally {
}
finally {
lock.unlock();
}
return payConfigStorage.getAccessToken();
@@ -84,27 +102,26 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
/**
* 登录 并获取登陆信息(授权码)
* @return 登陆信息
*
* @return 登陆信息
* @throws PayErrorException 支付异常
*/
public JSONObject login() throws PayErrorException {
TreeMap<String, String> data = new TreeMap<>();
data.put("username", payConfigStorage.getSeller());
data.put("password", payConfigStorage.getKeyPrivate());
String apbNonce = SignUtils.randomStr();
public JSONObject login() throws PayErrorException {
TreeMap<String, String> data = new TreeMap<>();
data.put("username", payConfigStorage.getSeller());
data.put("password", payConfigStorage.getKeyPrivate());
String apbNonce = SignUtils.randomStr();
// 1、确定请求主体为用户登录即需要传登录的用户名username和密码password并且要生成唯一的随机数命名为apb_nonce长度为32位
// 2、将所有的参数集进行key排序
// 3、将排序后的数组从起始位置拼接成字符串如password=XXXXXXXusername=XXXXX
// 4、将拼接出来的字符串连接上apb_nonce的值即AAAAAAAAAA。再连接 password=XXXXXXXusername=XXXXXAAAAAAAAAA
String sign = createSign(SignUtils.parameterText(data, "") + apbNonce, payConfigStorage.getInputCharset());
String queryParam = SignUtils.parameterText(data) + "&apb_nonce=" + apbNonce + "&sign=" + sign;
JSONObject json = execute(getReqUrl(YoudianTransactionType.LOGIN) + "?" + queryParam, MethodType.GET, null);
payConfigStorage.updateAccessToken(json.getString("access_token"), json.getLongValue("viptime"));
return json;
}
String sign = createSign(SignUtils.parameterText(data, "") + apbNonce, payConfigStorage.getInputCharset());
String queryParam = SignUtils.parameterText(data) + "&apb_nonce=" + apbNonce + "&sign=" + sign;
JSONObject json = execute(getReqUrl(YoudianTransactionType.LOGIN) + "?" + queryParam, MethodType.GET, null);
payConfigStorage.updateAccessToken(json.getString("access_token"), json.getLongValue("viptime"));
return json;
}
/**
@@ -115,15 +132,18 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
*/
@Override
public boolean verify(Map<String, Object> params) {
if (!"SUCCESS".equals(params.get("return_code"))){
if (!"SUCCESS".equals(params.get("return_code"))) {
LOG.debug(String.format("友店微信支付异常return_code=%s,参数集=%s", params.get("return_code"), params));
return false;
}
if(params.get("sign") == null) {LOG.debug("友店微信支付异常签名为空out_trade_no=" + params.get("out_trade_no"));}
if (params.get("sign") == null) {
LOG.debug("友店微信支付异常签名为空out_trade_no=" + params.get("out_trade_no"));
}
try {
return signVerify(params, (String) params.get("sign")) && verifySource((String)params.get("out_trade_no"));
} catch (PayErrorException e) {
return signVerify(params, (String) params.get("sign")) && verifySource((String) params.get("out_trade_no"));
}
catch (PayErrorException e) {
LOG.error(e.getMessage());
}
return false;
@@ -132,32 +152,32 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
/**
* 根据反馈回来的信息,生成签名结果
*
* @param params 通知返回来的参数数组
* @param sign 比对的签名结果
* @param sign 比对的签名结果
* @return 生成的签名结果
*/
@Override
public boolean signVerify(Map<String, Object> params, String sign) {
return SignUtils.valueOf(payConfigStorage.getSignType()).verify(params, sign, "&key=" + payConfigStorage.getKeyPublic(), payConfigStorage.getInputCharset());
}
/**
* 验证链接来源是否有效
* 校验数据来源
* @param id id 商户订单号扫码收款返回的order_sn
*
* @param id id 商户订单号扫码收款返回的order_sn
* @return true通过
*/
@Override
public boolean verifySource(String id) {
try {
JSONObject jsonObject = (JSONObject)query(id, null);
JSONObject jsonObject = (JSONObject) query(id, null);
return 0 == jsonObject.getIntValue("errorcode");
}catch (PayErrorException e){
if (Integer.parseInt(e.getPayError().getErrorCode()) >= 400){
}
catch (PayErrorException e) {
if (Integer.parseInt(e.getPayError().getErrorCode()) >= 400) {
throw e;
}
return false;
@@ -166,46 +186,47 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
}
/**
* 向友店端发送请求在这里执行的策略是当发生access_token过期时才去刷新然后重新执行请求而不是全局定时请求
*
* @param uri 请求地址
* @param method 请求方式
* @see MethodType#GET
* @see MethodType#POST
* @param uri 请求地址
* @param method 请求方式
* @param request 请求内容GET无需
* @return 请求成功后的结果
* @throws PayErrorException 支付异常
* @see MethodType#GET
* @see MethodType#POST
*/
public JSONObject execute(String uri, MethodType method, Object request) throws PayErrorException {
public JSONObject execute(String uri, MethodType method, Object request) throws PayErrorException {
int retryTimes = 0;
do {
try {
JSONObject result = requestTemplate.doExecute(uri, request, JSONObject.class, method);
if ( 0 != result.getIntValue("errorcode")){
throw new PayErrorException(new YdPayError(result.getIntValue("errorcode"), result.getString("msg"), result.toJSONString()));
}
return result;
}catch (PayErrorException e){
PayError error = e.getPayError();
if ("401".equals(error.getErrorCode()) || "500".equals(error.getErrorCode())) {
try {
int sleepMillis = retrySleepMillis * (1 << retryTimes);
LOG.debug(String.format("友店微信系统繁忙,(%s)ms 后重试(第%s次)", sleepMillis, retryTimes + 1));
Thread.sleep(sleepMillis);
} catch (InterruptedException e1) {
throw new PayErrorException(new YdPayError(-1, "友店支付服务端重试失败", e1.getMessage()));
try {
JSONObject result = requestTemplate.doExecute(uri, request, JSONObject.class, method);
if (0 != result.getIntValue("errorcode")) {
throw new PayErrorException(new YdPayError(result.getIntValue("errorcode"), result.getString("msg"), result.toJSONString()));
}
return result;
}
catch (PayErrorException e) {
PayError error = e.getPayError();
if ("401".equals(error.getErrorCode()) || "500".equals(error.getErrorCode())) {
try {
int sleepMillis = retrySleepMillis * (1 << retryTimes);
LOG.debug(String.format("友店微信系统繁忙,(%s)ms 后重试(第%s次)", sleepMillis, retryTimes + 1));
Thread.sleep(sleepMillis);
}
catch (InterruptedException e1) {
throw new PayErrorException(new YdPayError(-1, "友店支付服务端重试失败", e1.getMessage()));
}
// 强制设置wxMpConfigStorage它的access token过期了这样在下一次请求里就会刷新access token
payConfigStorage.expireAccessToken();
//进行重新登陆授权
login();
}
else {
throw e;
}
// 强制设置wxMpConfigStorage它的access token过期了这样在下一次请求里就会刷新access token
payConfigStorage.expireAccessToken();
//进行重新登陆授权
login();
}else {
throw e;
}
}
} while (++retryTimes < maxRetryTimes);
@@ -213,7 +234,6 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
}
/**
* 获取支付平台所需的订单信息
*
@@ -224,40 +244,41 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
@Override
public JSONObject orderInfo(PayOrder order) {
Map<String, Object> data = new TreeMap<>();
data.put("access_token", getAccessToken());
data.put("access_token", getAccessToken());
data.put("paymoney", Util.conversionAmount(order.getPrice()).toString());
data.putAll(order.getAttrs());
data = preOrderHandler(data, order);
data = preOrderHandler(data, order);
String apbNonce = SignUtils.randomStr();
String sign = createSign(SignUtils.parameterText(data, "") + apbNonce, payConfigStorage.getInputCharset());
data.put("PayMoney", data.remove("paymoney"));
String params = SignUtils.parameterText(data) + "&apb_nonce=" + apbNonce + "&sign=" + sign;
String params = SignUtils.parameterText(data) + "&apb_nonce=" + apbNonce + "&sign=" + sign;
try {
JSONObject json = execute(getReqUrl(order.getTransactionType())+ "?" + params, MethodType.GET, null);
JSONObject json = execute(getReqUrl(order.getTransactionType()) + "?" + params, MethodType.GET, null);
//友店比较特殊,需要在下完预订单后,自己存储 order_sn 对应 微信官方文档 out_trade_no
order.setOutTradeNo(json.getString("order_sn"));
order.setTradeNo(json.getString("order_sn"));
return json;
} catch (PayErrorException e) {
throw e;
}
catch (PayErrorException e) {
throw e;
}
}
/**
* 签名
* @param content 需要签名的内容
* @param characterEncoding 字符编码
*
* 1、确定请求主体为用户登录即需要传登录的用户名username和密码password并且要生成唯一的随机数命名为apb_nonce长度为32位
* 2、将所有的参数集进行key排序
* 3、将排序后的数组从起始位置拼接成字符串如password=XXXXXXXusername=XXXXX
* 4、将拼接出来的字符串连接上apb_nonce的值即AAAAAAAAAA。再连接 password=XXXXXXXusername=XXXXXAAAAAAAAAA
* @param content 需要签名的内容
* @param characterEncoding 字符编码
* <p>
* 1、确定请求主体为用户登录即需要传登录的用户名username和密码password并且要生成唯一的随机数命名为apb_nonce长度为32位
* 2、将所有的参数集进行key排序
* 3、将排序后的数组从起始位置拼接成字符串如password=XXXXXXXusername=XXXXX
* 4、将拼接出来的字符串连接上apb_nonce的值即AAAAAAAAAA。再连接 password=XXXXXXXusername=XXXXXAAAAAAAAAA
* @return 签名结果
*/
@Override
public String createSign(String content, String characterEncoding) {
return SignUtils.valueOf(payConfigStorage.getSignType().toUpperCase()).createSign(content, "&source=http://life.51youdian.com", characterEncoding);
return SignUtils.valueOf(payConfigStorage.getSignType().toUpperCase()).createSign(content, "&source=http://life.51youdian.com", characterEncoding);
}
/**
@@ -270,7 +291,7 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
@Override
public Map<String, Object> getParameter2Map(Map<String, String[]> parameterMap, InputStream is) {
Map<String, Object> params = new TreeMap<String, Object>();
for (Iterator iter = parameterMap.keySet().iterator(); iter.hasNext();) {
for (Iterator iter = parameterMap.keySet().iterator(); iter.hasNext(); ) {
String name = (String) iter.next();
String[] values = parameterMap.get(name);
String valueStr = "";
@@ -295,7 +316,6 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
*
* @param code return_code
* @param message return_msg
*
* @return 返回输出消息
*/
@Override
@@ -305,26 +325,28 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
builder.put("return_msg", message);
builder.put("nonce_str", SignUtils.randomStr());
String sgin = SignUtils.valueOf(payConfigStorage.getSignType()).sign(builder, "&key=" + payConfigStorage.getKeyPrivate(), payConfigStorage.getInputCharset());
return PayOutMessage.TEXT().content("{\"return_code\":\""+builder.get("return_code")+"\",\"return_msg\":\""+builder.get("return_msg")+"\",\"nonce_str\":\""+builder.get("nonce_str")+"\",\"sign\":\""+ sgin +"\"}").build();
return PayOutMessage.TEXT().content("{\"return_code\":\"" + builder.get("return_code") + "\",\"return_msg\":\"" + builder.get("return_msg") + "\",\"nonce_str\":\"" + builder.get("nonce_str") + "\",\"sign\":\"" + sgin + "\"}").build();
}
/**
* 获取成功输出消息,用户返回给支付端
* 主要用于拦截器中返回
*
* @param payMessage 支付回调消息
* @return 返回输出消息
*/
@Override
public PayOutMessage successPayOutMessage(PayMessage payMessage) {
return PayOutMessage.TEXT().content(JSON.toJSONString(payMessage.getPayMessage())).build();
return PayOutMessage.TEXT().content(JSON.toJSONString(payMessage.getPayMessage())).build();
}
/**
* 针对web端的即时付款
* 暂未实现或无此功能
* 暂未实现或无此功能
*
* @param orderInfo 发起支付的订单信息
* @param method 请求方式 &quot;post&quot; &quot;get&quot;,
* @param method 请求方式 &quot;post&quot; &quot;get&quot;,
* @return 获取输出消息,用户返回给支付端, 针对于web端
* @see MethodType 请求类型
*/
@@ -342,7 +364,8 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
}
/**
* 暂未实现或无此功能
* 暂未实现或无此功能
*
* @param order 发起支付的订单信息
* @return 返回支付结果
*/
@@ -364,16 +387,17 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
public Map<String, Object> query(String tradeNo, String outTradeNo) {
String apbNonce = SignUtils.randomStr();
TreeMap<String, String> data = new TreeMap<>();
data.put("access_token", payConfigStorage.getAccessToken());
data.put("access_token", payConfigStorage.getAccessToken());
if (StringUtils.isEmpty(tradeNo)){
if (StringUtils.isEmpty(tradeNo)) {
data.put("order_sn", outTradeNo);
}else {
}
else {
data.put("order_sn", tradeNo);
}
String sign = createSign(SignUtils.parameterText(data, "") + apbNonce, payConfigStorage.getInputCharset());
String queryParam = SignUtils.parameterText(data) + "&apb_nonce=" + apbNonce + "&sign=" + sign;
JSONObject jsonObject = execute(getReqUrl(YoudianTransactionType.NATIVE_STATUS) + "?" + queryParam, MethodType.GET, null);
String queryParam = SignUtils.parameterText(data) + "&apb_nonce=" + apbNonce + "&sign=" + sign;
JSONObject jsonObject = execute(getReqUrl(YoudianTransactionType.NATIVE_STATUS) + "?" + queryParam, MethodType.GET, null);
return jsonObject;
}
@@ -384,8 +408,6 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
}
/**
* 申请退款接口
*
@@ -396,20 +418,21 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
public RefundResult refund(RefundOrder refundOrder) {
String apbNonce = SignUtils.randomStr();
TreeMap<String, String> data = new TreeMap<>();
data.put("access_token", payConfigStorage.getAccessToken());
data.put("access_token", payConfigStorage.getAccessToken());
if (StringUtils.isEmpty(refundOrder.getOutTradeNo())){
if (StringUtils.isEmpty(refundOrder.getOutTradeNo())) {
data.put("order_sn", refundOrder.getOutTradeNo());
}else {
}
else {
data.put("order_sn", refundOrder.getTradeNo());
}
//支付类型刷卡为3扫码为4
data.put("type", "4");
data.put("refund_fee", refundOrder.getRefundAmount().setScale(2, BigDecimal.ROUND_HALF_UP).toString());
String sign = createSign(SignUtils.parameterText(data, "") + apbNonce, payConfigStorage.getInputCharset());
String queryParam = SignUtils.parameterText(data) + "&apb_nonce=" + apbNonce + "&sign=" + sign;
JSONObject jsonObject = execute(getReqUrl(YoudianTransactionType.REFUND) + "?" + queryParam, MethodType.GET, null);
return new BaseRefundResult() {
String queryParam = SignUtils.parameterText(data) + "&apb_nonce=" + apbNonce + "&sign=" + sign;
JSONObject jsonObject = execute(getReqUrl(YoudianTransactionType.REFUND) + "?" + queryParam, MethodType.GET, null);
return new BaseRefundResult(jsonObject) {
@Override
public String getCode() {
return getAttrString("errorcode");
@@ -471,26 +494,11 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
@Override
public Map<String, Object> downloadbill(Date billDate, String billType) {
public Map<String, Object> downloadbill(Date billDate, String billType) {
return Collections.emptyMap();
}
/**
* @param tradeNoOrBillDate 支付平台订单号或者账单类型, 具体请
* 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link PayErrorException}
* @param outTradeNoBillType 商户单号或者 账单类型
* @param transactionType 交易类型
*
* @return 返回支付方对应接口的结果
*/
@Override
public Map<String, Object> secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType) {
return Collections.emptyMap();
}
public WxYouDianPayService(WxYouDianPayConfigStorage payConfigStorage) {
super(payConfigStorage);
}
@@ -501,11 +509,12 @@ public class WxYouDianPayService extends BasePayService<WxYouDianPayConfigStorag
/**
* 根据交易类型获取请求地址
*
* @param type 交易类型
* @return 请求地址
*/
@Override
public String getReqUrl(TransactionType type){
public String getReqUrl(TransactionType type) {
return URL + type.getMethod();
}

View File

@@ -4,7 +4,8 @@ import com.egzosn.pay.common.api.BasePayConfigStorage;
/**
* 微信配置存储
* @author egan
*
* @author egan
*
* <pre>
* email egzosn@gmail.com
@@ -17,34 +18,32 @@ public class WxPayConfigStorage extends BasePayConfigStorage {
/**
* 微信分配的公众账号ID
*/
private String appid ;
private String appId;
/**
* 微信分配的子商户公众账号ID
*/
private String subAppid ;
private String subAppId;
/**
* 微信支付分配的商户号 合作者id
* 微信支付分配的商户号 合作者id
*/
private String mchId;
/**
* 微信支付分配的子商户号,开发者模式下必填 合作者id
* 微信支付分配的子商户号,开发者模式下必填 合作者id
*/
private String subMchId;
@Deprecated
@Override
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
return appId;
}
@Deprecated
public void setAppid(String appId) {
this.appId = appId;
}
/**
@@ -56,8 +55,6 @@ public class WxPayConfigStorage extends BasePayConfigStorage {
}
@Override
public String getSeller() {
return null;
@@ -73,7 +70,8 @@ public class WxPayConfigStorage extends BasePayConfigStorage {
}
/**
* 为商户平台设置的密钥key
* 为商户平台设置的密钥key
*
* @return 微信密钥
*/
public String getSecretKey() {
@@ -81,17 +79,50 @@ public class WxPayConfigStorage extends BasePayConfigStorage {
}
public void setSecretKey(String secretKey) {
setKeyPrivate(secretKey);
setKeyPrivate(secretKey);
}
public void setAppId(String appId) {
this.appId = appId;
}
/**
* 应用id
* 纠正名称
*
* @return 应用id
*/
@Override
public String getAppId() {
return appId;
}
public String getSubAppId() {
return subAppId;
}
public void setSubAppId(String subAppId) {
this.subAppId = subAppId;
}
/**
* 应用id
* 纠正名称
*
* @return 应用id
* @see #getSubAppId()
*/
@Deprecated
public String getSubAppid() {
return subAppid;
return subAppId;
}
@Deprecated
public void setSubAppid(String subAppid) {
this.subAppid = subAppid;
this.subAppId = subAppid;
}
public String getSubMchId() {
return subMchId;
}

View File

@@ -74,7 +74,7 @@ import com.egzosn.pay.wx.bean.WxTransferType;
* date 2016-5-18 14:09:01
* </pre>
*/
public class WxPayService extends BasePayService<WxPayConfigStorage> implements WxRedPackService,WxBillService {
public class WxPayService extends BasePayService<WxPayConfigStorage> implements WxRedPackService, WxBillService {
/**
@@ -132,7 +132,7 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
@Override
public boolean verify(Map<String, Object> params) {
if (null == params.get(SIGN) || !(SUCCESS.equals(params.get(RETURN_CODE)) && SUCCESS.equals(params.get(RESULT_CODE))) ) {
if (null == params.get(SIGN) || !(SUCCESS.equals(params.get(RETURN_CODE)) && SUCCESS.equals(params.get(RESULT_CODE)))) {
if (LOG.isErrorEnabled()) {
LOG.error(String.format("微信支付异常return_code=%s,参数集=%s", params.get(RETURN_CODE), params));
}
@@ -140,26 +140,15 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
}
try {
return signVerify(params, (String) params.get(SIGN)) && verifySource((String) params.get(OUT_TRADE_NO));
} catch (PayErrorException e) {
return signVerify(params, (String) params.get(SIGN));
}
catch (PayErrorException e) {
LOG.error(e);
}
return false;
}
/**
* 微信是否也需要再次校验来源,进行订单查询
*
* @param id 商户单号
* @return true通过
*/
@Override
public boolean verifySource(String id) {
return true;
}
/**
* 根据反馈回来的信息,生成签名结果
*
@@ -167,7 +156,6 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
* @param sign 比对的签名结果
* @return 生成的签名结果
*/
@Override
public boolean signVerify(Map<String, Object> params, String sign) {
return signVerify(params, sign, payConfigStorage.isTest());
}
@@ -190,11 +178,11 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
private Map<String, Object> getPublicParameters() {
Map<String, Object> parameters = new TreeMap<String, Object>();
parameters.put(APPID, payConfigStorage.getAppid());
parameters.put(APPID, payConfigStorage.getAppId());
parameters.put(MCH_ID, payConfigStorage.getMchId());
//判断如果是服务商模式信息则加入
setParameters(parameters, "sub_mch_id", payConfigStorage.getSubMchId());
setParameters(parameters, "sub_appid", payConfigStorage.getSubAppid());
setParameters(parameters, "sub_appid", payConfigStorage.getSubAppId());
parameters.put(NONCE_STR, SignUtils.randomStr());
return parameters;
@@ -289,7 +277,8 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
params.put("timeStamp", System.currentTimeMillis() / 1000);
params.put("nonceStr", result.get(NONCE_STR));
params.put("package", "prepay_id=" + result.get("prepay_id"));
} else if (WxTransactionType.APP == order.getTransactionType()) {
}
else if (WxTransactionType.APP == order.getTransactionType()) {
params.put("partnerid", payConfigStorage.getPid());
params.put(APPID, payConfigStorage.getAppid());
params.put("prepayid", result.get("prepay_id"));
@@ -391,7 +380,8 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
TreeMap<String, Object> map = new TreeMap<String, Object>();
try {
return XML.inputStream2Map(is, map);
} catch (IOException e) {
}
catch (IOException e) {
throw new PayErrorException(new PayException("IOException", e.getMessage()));
}
@@ -419,7 +409,7 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
*/
@Override
public PayOutMessage successPayOutMessage(PayMessage payMessage) {
return PayOutMessage.XML().code("Success").content("成功").build();
return PayOutMessage.XML().code("SUCCESS").content("成功").build();
}
@@ -471,7 +461,8 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
if (null == order.getTransactionType()) {
order.setTransactionType(WxTransactionType.MICROPAY);
} else if (WxTransactionType.MICROPAY != order.getTransactionType() && WxTransactionType.FACEPAY != order.getTransactionType()) {
}
else if (WxTransactionType.MICROPAY != order.getTransactionType() && WxTransactionType.FACEPAY != order.getTransactionType()) {
throw new PayErrorException(new PayException("-1", "错误的交易类型:" + order.getTransactionType()));
}
return orderInfo(order);
@@ -575,7 +566,7 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
*/
@Override
public Map<String, Object> downloadbill(Date billDate, String billType) {
Map<String, Object> parameters = getDownloadBillParam(billDate, billType,false);
Map<String, Object> parameters = getDownloadBillParam(billDate, billType, false);
//设置签名
setSign(parameters);
String respStr = requestTemplate.postForObject(getReqUrl(WxTransactionType.DOWNLOADBILL), XML.getMap2Xml(parameters), String.class);
@@ -595,25 +586,26 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
*
* @param billDate 账单类型商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型trade、signcustomertrade指商户基于支付宝交易收单的业务账单signcustomer是指基于商户支付宝余额收入及支出等资金变动的帐务账单
* @param billType 账单时间日账单格式为yyyy-MM-dd月账单格式为yyyy-MM。
* @param path 账单返回格式 账单存储的基础路径,按月切割
* @param path 账单返回格式 账单存储的基础路径,按月切割
* @return 返回支付方下载对账单的结果
*/
@Override
public Map<String, Object> downloadbill(Date billDate, String billType, String path) {
Map<String, Object> parameters = getDownloadBillParam(billDate, billType,true);
//设置签名
Map<String, Object> parameters = getDownloadBillParam(billDate, billType, true);
//设置签名
setSign(parameters);
InputStream inputStream = requestTemplate.postForObject(getReqUrl(WxTransactionType.DOWNLOADBILL), XML.getMap2Xml(parameters), InputStream.class);
try {
//解压流
inputStream = uncompress(inputStream);
writeToLocal(path+DateUtils.formatDate(new Date(), DateUtils.YYYYMM)+"/"+DateUtils.formatDate(new Date(), DateUtils.YYYYMMDDHHMMSS)+".txt", inputStream);
writeToLocal(path + DateUtils.formatDate(new Date(), DateUtils.YYYYMM) + "/" + DateUtils.formatDate(new Date(), DateUtils.YYYYMMDDHHMMSS) + ".txt", inputStream);
Map<String, Object> ret = new HashMap<String, Object>(3);
ret.put(RETURN_CODE, SUCCESS);
ret.put(RETURN_MSG_CODE, "ok");
ret.put("data", path);
return ret;
} catch (Exception e) {
}
catch (Exception e) {
e.printStackTrace();
Map<String, Object> ret = new HashMap<String, Object>(3);
ret.put(RETURN_CODE, FAIL);
@@ -627,8 +619,8 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
* GZIP解压缩
*
* @param input 输入流账单
* @return 解压后输入流
* @throws IOException IOException
* @return 解压后输入流
* @throws IOException IOException
*/
public static InputStream uncompress(InputStream input) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -644,6 +636,7 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
/**
* 将InputStream写入本地文件
*
* @param destination 写入本地目录
* @param inputStream 输入流
* @throws IOException IOException
@@ -651,45 +644,46 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
private void writeToLocal(String destination, InputStream inputStream)
throws IOException {
// 判断字节大小
if (inputStream.available() != 0) {
System.out.println("结果大小:" + inputStream.available());
File file = new File(destination);
if (!file.getParentFile().exists()) {
boolean result = file.getParentFile().mkdirs();
if (!result) {
System.out.println("创建失败");
}
// 判断字节大小
if (inputStream.available() != 0) {
System.out.println("结果大小:" + inputStream.available());
File file = new File(destination);
if (!file.getParentFile().exists()) {
boolean result = file.getParentFile().mkdirs();
if (!result) {
System.out.println("创建失败");
}
OutputStream out = new FileOutputStream(file);
int size = 0;
int len = 0;
byte[] buf = new byte[1024];
while ((size = inputStream.read(buf)) != -1) {
len += size;
out.write(buf, 0, size);
}
System.out.println("最终写入字节数大小:" + len);
inputStream.close();
out.close();
}
OutputStream out = new FileOutputStream(file);
int size = 0;
int len = 0;
byte[] buf = new byte[1024];
while ((size = inputStream.read(buf)) != -1) {
len += size;
out.write(buf, 0, size);
}
System.out.println("最终写入字节数大小:" + len);
inputStream.close();
out.close();
}
}
/**
* 下载账单公共参数
*
* @param billDate 账单类型商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型trade、signcustomertrade指商户基于支付宝交易收单的业务账单signcustomer是指基于商户支付宝余额收入及支出等资金变动的帐务账单
* @param billType 账单时间日账单格式为yyyy-MM-dd月账单格式为yyyy-MM。
* @param tarType 账单返回格式 默认返回流false gzip 时候true
* @param tarType 账单返回格式 默认返回流false gzip 时候true
* @return
*/
private Map<String, Object> getDownloadBillParam(Date billDate, String billType,boolean tarType) {
private Map<String, Object> getDownloadBillParam(Date billDate, String billType, boolean tarType) {
//获取公共参数
Map<String, Object> parameters = getPublicParameters();
parameters.put("bill_type", billType);
//目前只支持日账单
parameters.put("bill_date", DateUtils.formatDate(billDate, DateUtils.YYYYMMDD));
if(tarType){
if (tarType) {
parameters.put("tar_type", "GZIP");
}
return parameters;
@@ -702,7 +696,6 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
* @param transactionType 交易类型
* @return 返回支付方对应接口的结果
*/
@Override
public Map<String, Object> secondaryInterface(Object transactionIdOrBillDate, String outTradeNoBillType, TransactionType transactionType) {
if (transactionType == WxTransactionType.REFUND) {
@@ -735,12 +728,12 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
* @param order 转账订单
* <pre>
*
* 注意事项:
* ◆ 当返回错误码为“SYSTEMERROR”时请不要更换商户订单号一定要使用原商户订单号重试否则可能造成重复支付等资金风险。
* ◆ XML具有可扩展性因此返回参数可能会有新增而且顺序可能不完全遵循此文档规范如果在解析回包的时候发生错误请商户务必不要换单重试请商户联系客服确认付款情况。如果有新回包字段会更新到此API文档中。
* ◆ 因为错误代码字段err_code的值后续可能会增加所以商户如果遇到回包返回新的错误码请商户务必不要换单重试请商户联系客服确认付款情况。如果有新的错误码会更新到此API文档中。
* ◆ 错误代码描述字段err_code_des只供人工定位问题时做参考系统实现时请不要依赖这个字段来做自动化处理。
* </pre>
* 注意事项:
* ◆ 当返回错误码为“SYSTEMERROR”时请不要更换商户订单号一定要使用原商户订单号重试否则可能造成重复支付等资金风险。
* ◆ XML具有可扩展性因此返回参数可能会有新增而且顺序可能不完全遵循此文档规范如果在解析回包的时候发生错误请商户务必不要换单重试请商户联系客服确认付款情况。如果有新回包字段会更新到此API文档中。
* ◆ 因为错误代码字段err_code的值后续可能会增加所以商户如果遇到回包返回新的错误码请商户务必不要换单重试请商户联系客服确认付款情况。如果有新的错误码会更新到此API文档中。
* ◆ 错误代码描述字段err_code_des只供人工定位问题时做参考系统实现时请不要依赖这个字段来做自动化处理。
* </pre>
* @return 对应的转账结果
*/
@Override
@@ -757,7 +750,8 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
if (null != order.getTransferType() && TRANSFERS == order.getTransferType()) {
transfers(parameters, order);
parameters.put("mchid", payConfigStorage.getPid());
} else {
}
else {
parameters.put(MCH_ID, payConfigStorage.getPid());
order.setTransferType(WxTransferType.PAY_BANK);
payBank(parameters, order);
@@ -842,7 +836,8 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
public String keyPublic(String content) {
try {
return RSA2.encrypt(content, payConfigStorage.getKeyPublic(), CIPHER_ALGORITHM, payConfigStorage.getInputCharset());
} catch (GeneralSecurityException | IOException e) {
}
catch (GeneralSecurityException | IOException e) {
throw new PayErrorException(new WxPayError(FAILURE, e.getLocalizedMessage()));
}
}
@@ -873,7 +868,8 @@ public class WxPayService extends BasePayService<WxPayConfigStorage> implements
//现金红包小程序红包默认传1.裂变红包取传入值且需要大于3
parameters.put("total_num", Math.max(redpackOrder.getTotalNum(), 3));
parameters.put("amt_type", "ALL_RAND");
} else if (WxSendredpackType.SENDMINIPROGRAMHB == redpackOrder.getTransferType()) {
}
else if (WxSendredpackType.SENDMINIPROGRAMHB == redpackOrder.getTransferType()) {
parameters.put("notify_way", "MINI_PROGRAM_JSAPI");
}

View File

@@ -4,7 +4,8 @@ import com.egzosn.pay.common.api.BasePayConfigStorage;
/**
* 易极付配置存储
* @author egan
*
* @author egan
*
* <pre>
* email egzosn@gmail.com
@@ -15,14 +16,14 @@ public class YiJiPayConfigStorage extends BasePayConfigStorage {
/**
* 易极付分配的商户号 合作者id
* 易极付分配的商户号 合作者id
*/
private String partnerId;
/**
* 卖家id
*/
private String sellerUserId;
private String sellerUserId;
public String getPartnerId() {
return partnerId;
@@ -37,6 +38,17 @@ public class YiJiPayConfigStorage extends BasePayConfigStorage {
return null;
}
/**
* 应用id
* 纠正名称
*
* @return 应用id
*/
@Override
public String getAppId() {
return null;
}
/**
* 合作商唯一标识
@@ -47,8 +59,6 @@ public class YiJiPayConfigStorage extends BasePayConfigStorage {
}
@Override
public String getSeller() {
return sellerUserId;
@@ -63,7 +73,8 @@ public class YiJiPayConfigStorage extends BasePayConfigStorage {
}
/**
* 为商户平台设置的密钥key
* 为商户平台设置的密钥key
*
* @return 密钥
*/
public String getSecretKey() {
@@ -71,7 +82,7 @@ public class YiJiPayConfigStorage extends BasePayConfigStorage {
}
public void setSecretKey(String secretKey) {
setKeyPrivate(secretKey);
setKeyPrivate(secretKey);
}

View File

@@ -1,30 +1,39 @@
package com.egzosn.pay.yiji.api;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.common.api.BasePayService;
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.DateUtils;
import com.egzosn.pay.common.util.Util;
import com.egzosn.pay.common.util.sign.SignUtils;
import com.egzosn.pay.common.util.str.StringUtils;
import com.egzosn.pay.yiji.bean.YiJiTransactionType;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.common.api.BasePayService;
import com.egzosn.pay.common.bean.BaseRefundResult;
import com.egzosn.pay.common.bean.CurType;
import com.egzosn.pay.common.bean.DefaultCurType;
import com.egzosn.pay.common.bean.MethodType;
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.bean.TransferOrder;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.common.util.DateUtils;
import com.egzosn.pay.common.util.Util;
import com.egzosn.pay.common.util.sign.SignUtils;
import com.egzosn.pay.common.util.str.StringUtils;
import com.egzosn.pay.yiji.bean.YiJiTransactionType;
/**
* 易极付支付服务
*
* @author egan
* <p>
* email egzosn@gmail.com
* * date 2019/04/15 22:51
* <p>
* email egzosn@gmail.com
* * date 2019/04/15 22:51
*/
public class YiJiPayService extends BasePayService<YiJiPayConfigStorage> {
@@ -54,11 +63,13 @@ public class YiJiPayService extends BasePayService<YiJiPayConfigStorage> {
*/
@Override
public String getReqUrl(TransactionType transactionType) {
if (payConfigStorage.isTest()){
if (payConfigStorage.isTest()) {
return DEV_REQ_URL;
}else if (/*YiJiTransactionType.corderRemittanceSynOrder == transactionType ||*/ YiJiTransactionType.applyRemittranceWithSynOrder == transactionType){
}
else if (/*YiJiTransactionType.corderRemittanceSynOrder == transactionType ||*/ YiJiTransactionType.applyRemittranceWithSynOrder == transactionType) {
return HTTPS_GLOBAL_REQ_URL;
}else {
}
else {
return HTTPS_REQ_URL;
}
}
@@ -72,7 +83,6 @@ public class YiJiPayService extends BasePayService<YiJiPayConfigStorage> {
}
/**
* 回调校验
*
@@ -98,25 +108,12 @@ public class YiJiPayService extends BasePayService<YiJiPayConfigStorage> {
* @param sign 比对的签名结果
* @return 生成的签名结果
*/
@Override
public boolean signVerify(Map<String, Object> params, String sign) {
return SignUtils.valueOf(payConfigStorage.getSignType()).verify(params, sign, payConfigStorage.getKeyPublic(), payConfigStorage.getInputCharset());
}
/**
* 校验数据来源
*
* @param id 业务id, 数据的真实性.
* @return true通过
*/
@Override
public boolean verifySource(String id) {
return true;
}
/**
* 生成并设置签名
*
@@ -160,18 +157,18 @@ public class YiJiPayService extends BasePayService<YiJiPayConfigStorage> {
orderInfo.put("orderNo", order.getOutTradeNo());
orderInfo.put("outOrderNo", order.getOutTradeNo());
if (StringUtils.isNotEmpty(payConfigStorage.getSeller())){
if (StringUtils.isNotEmpty(payConfigStorage.getSeller())) {
orderInfo.put("sellerUserId", payConfigStorage.getSeller());
}
((YiJiTransactionType)order.getTransactionType()).setAttribute(orderInfo, order);
((YiJiTransactionType) order.getTransactionType()).setAttribute(orderInfo, order);
orderInfo.put("tradeAmount", Util.conversionAmount(order.getPrice()));
//商品条款信息 商品名称
orderInfo.put("goodsClauses", String.format("[{'name':'%s'}]", order.getBody()));
//交易名称
orderInfo.put("tradeName", order.getSubject());
if (null != order.getCurType()){
if (null != order.getCurType()) {
orderInfo.put("currency", order.getCurType());
}
orderInfo.putAll(order.getAttrs());
@@ -292,8 +289,6 @@ public class YiJiPayService extends BasePayService<YiJiPayConfigStorage> {
}
/**
* 申请退款接口
*
@@ -384,20 +379,6 @@ public class YiJiPayService extends BasePayService<YiJiPayConfigStorage> {
}
/**
* @param tradeNoOrBillDate 支付平台订单号或者账单类型, 具体请
* 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link PayErrorException}
* @param outTradeNoBillType 商户单号或者 账单类型
* @param transactionType 交易类型
* @return 返回支付方对应接口的结果
*/
@Override
public Map<String, Object> secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType) {
return Collections.emptyMap();
}
/**
* 转账 这里外部进行调用{@link #buildRequest(Map, MethodType)}
*
@@ -409,10 +390,10 @@ public class YiJiPayService extends BasePayService<YiJiPayConfigStorage> {
Map<String, Object> data = getPublicParameters(YiJiTransactionType.applyRemittranceWithSynOrder);
data.put("remittranceBatchNo", order.getBatchNo());
data.put("outOrderNo", order.getOutNo());
data.put("payAmount", Util.conversionAmount(order.getAmount()) );
data.put("payAmount", Util.conversionAmount(order.getAmount()));
data.put("payCurrency", order.getCurType().getType());
data.put("withdrawCurrency", DefaultCurType.CNY.getType());
data.put("payMemo",order.getRemark());
data.put("payMemo", order.getRemark());
data.put("toCountryCode", order.getCountryCode().getCode());
data.put("tradeUseCode", "326");
data.put("payeeName", order.getPayeeName());