/**
* 支付类型
* @author egan
* email [email protected]
* date 2016/11/20 0:30
*/
public enum PayType implements BasePayType {
aliPay {
/**
* @see com.egzosn.pay.ali.api.AliPayService
* @param apyAccount
* @return
*/
@ Override
public PayService getPayService (ApyAccount apyAccount ) {
AliPayConfigStorage aliPayConfigStorage = new AliPayConfigStorage ();
aliPayConfigStorage .setPid (apyAccount .getPartner ());
aliPayConfigStorage .setAppId (apyAccount .getAppid ());
aliPayConfigStorage .setKeyPublic (apyAccount .getPublicKey ());
aliPayConfigStorage .setKeyPrivate (apyAccount .getPrivateKey ());
aliPayConfigStorage .setNotifyUrl (apyAccount .getNotifyUrl ());
aliPayConfigStorage .setReturnUrl (apyAccount .getReturnUrl ());
aliPayConfigStorage .setSignType (apyAccount .getSignType ());
aliPayConfigStorage .setSeller (apyAccount .getSeller ());
aliPayConfigStorage .setPayType (apyAccount .getPayType ().toString ());
aliPayConfigStorage .setMsgType (apyAccount .getMsgType ());
aliPayConfigStorage .setInputCharset (apyAccount .getInputCharset ());
return new AliPayService (aliPayConfigStorage );
}
@ Override
public TransactionType getTransactionType (String transactionType ) {
// com.egzosn.pay.ali.bean.AliTransactionType 17年更新的版本,旧版本请自行切换{@link com.egzosn.pay.ali.before.bean.AliTransactionType}
return AliTransactionType .valueOf (transactionType );
}
},wxPay {
@ Override
public PayService getPayService (ApyAccount apyAccount ) {
WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage ();
wxPayConfigStorage .setMchId (apyAccount .getPartner ());
wxPayConfigStorage .setAppSecret (apyAccount .getPublicKey ());
wxPayConfigStorage .setKeyPublic (apyAccount .getPublicKey ());
wxPayConfigStorage .setAppId (apyAccount .getAppid ());
wxPayConfigStorage .setKeyPrivate (apyAccount .getPrivateKey ());
wxPayConfigStorage .setNotifyUrl (apyAccount .getNotifyUrl ());
wxPayConfigStorage .setSignType (apyAccount .getSignType ());
wxPayConfigStorage .setPayType (apyAccount .getPayType ().toString ());
wxPayConfigStorage .setMsgType (apyAccount .getMsgType ());
wxPayConfigStorage .setInputCharset (apyAccount .getInputCharset ());
return new WxPayService (wxPayConfigStorage );
}
/**
* 根据支付类型获取交易类型
* @param transactionType 类型值
* @see com.egzosn.pay.wx.bean.WxTransactionType
* @return
*/
@ Override
public TransactionType getTransactionType (String transactionType ) {
return WxTransactionType .valueOf (transactionType );
}
},youdianPay {
@ Override
public PayService getPayService (ApyAccount apyAccount ) {
// TODO 2017/1/23 14:12 author: egan 集群的话,友店可能会有bug。暂未测试集群环境
WxYouDianPayConfigStorage wxPayConfigStorage = new WxYouDianPayConfigStorage ();
wxPayConfigStorage .setKeyPrivate (apyAccount .getPrivateKey ());
wxPayConfigStorage .setKeyPublic (apyAccount .getPublicKey ());
// wxPayConfigStorage.setNotifyUrl(apyAccount.getNotifyUrl());
// 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 ());
return new WxYouDianPayService (wxPayConfigStorage );
}
/**
* 根据支付类型获取交易类型
* @param transactionType 类型值
* @see com.egzosn.pay.wx.youdian.bean.YoudianTransactionType
* @return
*/
@ Override
public TransactionType getTransactionType (String transactionType ) {
return YoudianTransactionType .valueOf (transactionType );
}
};
public abstract PayService getPayService (ApyAccount apyAccount );
}
/**
* 支付响应对象
* @author: egan
* email [email protected]
* date 2016/11/18 0:34
*/
public class PayResponse {
@ Resource
private AutowireCapableBeanFactory spring ;
private PayConfigStorage storage ;
private PayService service ;
private PayMessageRouter router ;
public PayResponse () {
}
/**
* 初始化支付配置
* @param apyAccount 账户信息
* @see ApyAccount 对应表结构详情--》 /pay-java-demo/resources/apy_account.sql
*/
public void init (ApyAccount apyAccount ) {
//根据不同的账户类型 初始化支付配置
this .service = apyAccount .getPayType ().getPayService (apyAccount );
this .storage = service .getPayConfigStorage ();
//这里设置代理配置
// service.setRequestTemplateConfigStorage(getHttpConfigStorage());
buildRouter (apyAccount .getPayId ());
}
/**
* 获取http配置,如果配置为null则为默认配置,无代理,无证书的请求方式。
* 此处非必需
* @param apyAccount 账户信息
* @return 请求配置
*/
public HttpConfigStorage getHttpConfigStorage (ApyAccount apyAccount ){
HttpConfigStorage httpConfigStorage = new HttpConfigStorage ();
/*
//http代理地址
httpConfigStorage.setHttpProxyHost("192.168.1.69");
//代理端口
httpConfigStorage.setHttpProxyPort(3308);
//代理用户名
httpConfigStorage.setAuthUsername("user");
//代理密码
httpConfigStorage.setAuthPassword("password");
*/
//设置ssl证书路径
httpConfigStorage .setKeystore (apyAccount .getKeystorePath ());
//设置ssl证书对应的密码
httpConfigStorage .setStorePassword (apyAccount .getStorePassword ());
return httpConfigStorage ;
}
/**
* 配置路由
* @param payId 指定账户id,用户多微信支付多支付宝支付
*/
private void buildRouter (Integer payId ) {
router = new PayMessageRouter (this .service );
router
.rule ()
.msgType (MsgType .text .name ()) //消息类型
.payType (PayType .aliPay .name ()) //支付账户事件类型
.transactionType (AliTransactionType .UNAWARE .name ())//交易类型,有关回调的可在这处理
.interceptor (new AliPayMessageInterceptor (payId )) //拦截器
.handler (autowire (new AliPayMessageHandler (payId ))) //处理器
.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 ())
.handler (autowire (new YouDianPayMessageHandler (payId )))
.end ()
;
}
private PayMessageHandler autowire (PayMessageHandler handler ) {
spring .autowireBean (handler );
return handler ;
}
public PayConfigStorage getStorage () {
return storage ;
}
public PayService getService () {
return service ;
}
public PayMessageRouter getRouter () {
return router ;
}
}
/**
* 微信支付回调处理器
* Created by ZaoSheng on 2016/6/1.
*/
public class WxPayMessageHandler extends BasePayMessageHandler {
public WxPayMessageHandler (Integer payId ) {
super (payId );
}
@ Override
public PayOutMessage handle (PayMessage payMessage , Map <String , Object > context , PayService payService ) throws PayErrorException {
//交易状态
if ("SUCCESS" .equals (payMessage .getPayMessage ().get ("result_code" ))){
/////这里进行成功的处理
return payService .getPayOutMessage ("SUCCESS" , "OK" );
}
return payService .getPayOutMessage ("FAIL" , "失败" );
}
}
/**
* 支付宝回调信息拦截器
* @author: egan
* email [email protected]
* date 2017/1/18 19:28
*/
public class AliPayMessageInterceptor implements PayMessageInterceptor {
/**
* 拦截支付消息
*
* @param payMessage 支付回调消息
* @param context 上下文,如果handler或interceptor之间有信息要传递,可以用这个
* @param payService
* @return true代表OK,false代表不OK并直接中断对应的支付处理器
* @see PayMessageHandler 支付处理器
*/
@ Override
public boolean intercept (PayMessage payMessage , Map <String , Object > context , PayService payService ) throws PayErrorException {
//这里进行拦截器处理,自行实现
return true ;
}
}
public class ApyAccountService {
@ Inject
private ApyAccountDao dao ;
@ Inject
private AutowireCapableBeanFactory spring ;
private final static Map <Integer , PayResponse > payResponses = new HashMap <Integer , PayResponse >();
/**
* 获取支付响应
* @param id 账户id
* @return
*/
public PayResponse getPayResponse (Integer id ) {
PayResponse payResponse = payResponses .get (id );
if (payResponse == null ) {
ApyAccount apyAccount = dao .get (id );
if (apyAccount == null ) {
throw new IllegalArgumentException ("无法查询" );
}
payResponse = new PayResponse ();
spring .autowireBean (payResponse );
payResponse .init (apyAccount );
payResponses .put (id , payResponse );
// 查询
}
return payResponse ;
}
}
4.根据账户id与业务id,组拼订单信息(支付宝、微信支付订单)获取支付信息所需的数据
/**
* 跳到支付页面
* 针对实时支付,即时付款
*
* @param payId 账户id
* @param transactionType 交易类型, 这个针对于每一个 支付类型的对应的几种交易方式
* @param bankType 针对刷卡支付,卡的类型,类型值
* @return
*/
@ RequestMapping (value = "toPay.html" , produces = "text/html;charset=UTF-8" )
public String toPay ( Integer payId , String transactionType , String bankType , BigDecimal price ) {
//获取对应的支付账户操作工具(可根据账户id)
PayResponse payResponse = service .getPayResponse (payId );
PayOrder order = new PayOrder ("订单title" , "摘要" , null == price ? BigDecimal .valueOf (0.01 ) : price , UUID .randomUUID ().toString ().replace ("-" , "" ), PayType .valueOf (payResponse .getStorage ().getPayType ()).getTransactionType (transactionType ));
//此处只有刷卡支付(银行卡支付)时需要
if (StringUtils .isNotEmpty (bankType )){
order .setBankType (bankType );
}
Map orderInfo = payResponse .getService ().orderInfo (order );
return payResponse .getService ().buildRequest (orderInfo , MethodType .POST );
}
/**
* 获取二维码图像
* 二维码支付
* @return
*/
@ RequestMapping (value = "toQrPay.jpg" , produces = "image/jpeg;charset=UTF-8" )
public byte [] toWxQrPay (Integer payId , String transactionType , BigDecimal price ) throws IOException {
//获取对应的支付账户操作工具(可根据账户id)
PayResponse payResponse = service .getPayResponse (payId );
//获取订单信息
Map <String , Object > orderInfo = payResponse .getService ().orderInfo (new PayOrder ("订单title" , "摘要" , null == price ? BigDecimal .valueOf (0.01 ) : price , UUID .randomUUID ().toString ().replace ("-" , "" ), PayType .valueOf (payResponse .getStorage ().getPayType ()).getTransactionType (transactionType )));
ByteArrayOutputStream baos = new ByteArrayOutputStream ();
ImageIO .write (payResponse .getService ().genQrPay (orderInfo ), "JPEG" , baos );
return baos .toByteArray ();
}
/**
*
* 获取支付预订单信息
* @param payId 支付账户id
* @param transactionType 交易类型
* @return
*/
@ RequestMapping ("getOrderInfo" )
public Map <String , Object > getOrderInfo (Integer payId , String transactionType , BigDecimal price ){
//获取对应的支付账户操作工具(可根据账户id)
PayResponse payResponse = service .getPayResponse (payId );
Map <String , Object > data = new HashMap <>();
data .put ("code" , 0 );
PayOrder order = new PayOrder ("订单title" , "摘要" , null == price ? BigDecimal .valueOf (0.01 ) : price , UUID .randomUUID ().toString ().replace ("-" , "" ), PayType .valueOf (payResponse .getStorage ().getPayType ()).getTransactionType (transactionType ));
data .put ("orderInfo" , payResponse .getService ().orderInfo (order ));
return data ;
}
/**
* 查询
* @param order 订单的请求体
* @return
*/
@ RequestMapping ("query" )
public Map <String , Object > query (QueryOrder order ) {
PayResponse payResponse = service .getPayResponse (order .getPayId ());
return payResponse .getService ().query (order .getTradeNo (), order .getOutTradeNo ());
}
/**
* 交易关闭接口
* @param order 订单的请求体
* @return
*/
@ RequestMapping ("close" )
public Map <String , Object > close (QueryOrder order ) {
PayResponse payResponse = service .getPayResponse (order .getPayId ());
return payResponse .getService ().close (order .getTradeNo (), order .getOutTradeNo ());
}
/**
* 申请退款接口
* @param order 订单的请求体
* @return
*/
@ RequestMapping ("refund" )
public Map <String , Object > refund (QueryOrder order ) {
PayResponse payResponse = service .getPayResponse (order .getPayId ());
return payResponse .getService ().refund (order .getTradeNo (), order .getOutTradeNo (), order .getRefundAmount (), order .getTotalAmount ());
}
/**
* 查询退款
* @param order 订单的请求体
* @return
*/
@ RequestMapping ("refundquery" )
public Map <String , Object > refundquery (QueryOrder order ) {
PayResponse payResponse = service .getPayResponse (order .getPayId ());
return payResponse .getService ().refundquery (order .getTradeNo (), order .getOutTradeNo ());
}
/**
* 下载对账单
* @param order 订单的请求体
* @return
*/
@ RequestMapping ("downloadbill" )
public Object downloadbill (QueryOrder order ) {
PayResponse payResponse = service .getPayResponse (order .getPayId ());
return payResponse .getService ().downloadbill (order .getBillDate (), order .getBillType ());
}
/**
* 通用查询接口,根据 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 , new Callback <Map <String , Object >>() {
@ Override
public Map <String , Object > perform (Map <String , Object > map ) {
return map ;
}
});
}
/**
* 支付回调地址
* @param request
* @return
*/
@ RequestMapping (value = "payBack{payId}.json" )
public String payBack (HttpServletRequest request , @ PathVariable Integer payId ) throws IOException {
//根据账户id,获取对应的支付账户操作工具
PayResponse payResponse = service .getPayResponse (payId );
PayConfigStorage storage = payResponse .getStorage ();
//获取支付方返回的对应参数
Map <String , String > params = payResponse .getService ().getParameter2Map (request .getParameterMap (), request .getInputStream ());
if (null == params ){
return payResponse .getService ().getPayOutMessage ("fail" ,"失败" ).toMessage ();
}
//校验
if (payResponse .getService ().verify (params )){
PayMessage message = new PayMessage (params , storage .getPayType (), storage .getMsgType ().name ());
PayOutMessage outMessage = payResponse .getRouter ().route (message );
return outMessage .toMessage ();
}
return payResponse .getService ().getPayOutMessage ("fail" ,"失败" ).toMessage ();
}