jeepay支付系统
已完成了如下接口的对接工作:
支付宝官方普通商户模式/ isv模式 (RSA / RSA2加密 / 证书加密)
微信官方普通商户/服务商模式 (V2 / V3接口)
云闪付开放平台服务商模式
若您有更多的三方/银行接口 需要对接联调请参考以下文档进行二次开发,也可以联系官方技术收费开发(QQ:
13527422
)。
一、 接口准备工作:
1.1 > 接口起名:
按照jeepay项目的约定: 所有支付接口需全部小写,并且以pay
结尾, 例如 alipay
, wxpay
, ysfpay
比方我们待对接的通道为工行支付,起名 icbcpay
, 以下文档按照icbcpay
进行说明。
1.2 > 准备三方支付接口:
支付下单接口;
回调通知接口;
订单查询接口;
获取三方用户ID(非必须)
1.3 > 支付方式初始化:
jeepay支付平台已初始化微信、支付宝、云闪付常用支付方式,详见: [ 支付配置 / 支付方式 ] 功能列表。
若对接的接口需要支持其他支付方式, 比如需要支持工行APP支付,则起名为:ICBC_APP
。然后对ICBC_APP进行初始化操作, 支持DML插入和页面操作两种方式。
方式a>. 执行sql请插入t_pay_way
表。
方式b>. 页面操作如图:
注意: way_code
字段为大写。
1.4 > 支付接口初始化:
支付接口是对上游接口的定义内容, 包括接口代码, 名称, 是否支付普通商户, 是否支持服务商模式,支持的支付方式以及服务商、普通商户的配置参数定义等设置项。
支持DML插入和页面操作两种方式。
方式a>. 执行sql请插入t_pay_interface_define
表。
方式b>. 页面操作如图:
注意:
if_code
字段为小写。isv_params
isvsub_mch_params
normal_mch_params
三个字段为动态配置项,需存入JSONArray数组。规则如下:
//文本类型示例:
{
name: "appId", //定义取值key
desc: "应用ID", //描述信息
type: "text", //text 表示文本类型
verify: "required" //是否必填: required表示必填
}
//多行文本类型示例:
{
name: "privateKey", //定义取值key
desc: "私钥", //描述信息
type: "textarea", //textarea 表示多行文本类型
verify: "required" //是否必填: required表示必填
}
//单选按钮类型示例:
{
name: "sandbox", //定义取值key
desc: "环境配置", //描述信息
type: "radio", //radio表示为单选按钮
values: "1,0", //选中的值, 以英文逗号分隔 (values只有radio生效)
titles: "沙箱环境,生产环境", //显示标题, 以英文逗号分隔 (titles只有radio生效)
verify: "required" //是否必填
}
//文件类型示例:
{
name: "alipayRootCert", //定义取值key
desc: "支付宝根证书(.crt格式)", //描述信息
type: "file", //file表示上传文件类型
verify: "required" //是否必填: required表示必填
}
二、 接口编码:
2.1 > 添加支付接口常量:
在常量类(com.jeequan.jeepay.core.constants.CS)IF_CODE
和 PAY_WAY_CODE
接口中定义好待添加的支付接口和支付方式。
2.2 > 添加支付接口参数配置model:
按照第一步1.4中的配置约定信息,将参数定义好java bean
并统一放置在: com.jeequan.jeepay.core.model.params.对接接口代码
(core项目),定义bean 使得支付通道对接时更加方便。
需注意:
定义的参数bean 需要根据 服务商 / 普通商户类型继承不同的抽象类。
以icbcpay
为例:
a. 支持服务商模式:
服务商配置参数: 类起名 IcbcpayIsvParams
继承IsvParams
特约商户配置参数: 类起名 IcbcpayIsvsubMchParams
继承IsvsubMchParams
b. 普通商户模式:
普通商户配置参数: 类起名 IcbcpayNormalMchParams
继承NormalMchParams
同时需要在 IsvParams
IsvsubMchParams
NormalMchParams
中修改对应的工厂函数实现。 关键!!
2.3 > 添加支付方式的RQ和RS (如果有)
jeepay支付平台所有的API请求和响应,全部有model对应,并且支持hibernate validator校验 通用校验。
如果有新增的支付方式, 需要在 com.jeequan.jeepay.core.model.rqrs.payorder.payway
中进行定义。
以ICBC_APP
为例:
a. 新建 IcbcAppOrderRQ 继承 UnifiedOrderRQ
。
构造函数中将wayCode传入为 ICBC_APP 支付方式。 支持自定义字段,下单时可根据该支付方式进行传参。
新建RQ后需要同步在: com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ#buildBizRQ 函数中完成RQ的构造工作。
用于在不同的接口传入不同的业务RQ。 重要!!!
hibernate validator 的使用请参考: https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#validator-gettingstarted-createproject
示例
b. 新建 IcbcAppOrderRS 继承 UnifiedOrderRS
覆写: buildPayDataType 和 buildPayData 函数, 用于统一下单接口返回的payData数据。
同时支持自定义接口响应参数(仅单独支付方式接口时可用)。
示例
2.4 > 通道的对接工作
jeepay支付平台在 com.jeequan.jeepay.thirdparty.channel
包下定义好对应的接口, 根据不同业务实现不同的接口即可。
说明:
IChannelUserService
: 获取渠道用户ID的接口定义
IPaymentService
: 调起渠道侧下单支付接口定义
IChannelNoticeService
: 渠道回调通知解析数据定义
public interface IChannelNoticeService {
/** 通知类型 **/
enum NoticeTypeEnum {
DO_RETURN, //同步跳转
DO_NOTIFY //异步回调
}
/* 获取到接口code **/
String getIfCode();
/** 解析参数: 订单号 和 请求参数
* 异常需要自行捕捉,并返回null , 表示已响应数据。
* **/
MutablePair<String, Object> parseParams(HttpServletRequest request, String urlOrderId, NoticeTypeEnum noticeTypeEnum);
/** 返回需要更新的订单状态 和响应数据 **/
ChannelRetMsg doNotice(HttpServletRequest request,
Object params, PayOrder payOrder, MchConfigContext mchConfigContext, NoticeTypeEnum noticeTypeEnum);
/** 数据库订单 状态更新异常 (仅异步通知使用) **/
ResponseEntity doNotifyOrderStateUpdateFail(HttpServletRequest request);
/** 数据库订单数据不存在 (仅异步通知使用) **/
ResponseEntity doNotifyOrderNotExists(HttpServletRequest request);
}
IPayOrderQueryService
: 查单(渠道侧)接口定义
已icbcpay
为例
首先在com.jeequan.jeepay.thirdparty.channel
下新建 icbcpay 包: com.jeequan.jeepay.thirdparty.channel.icbcpay
a. 支付接口类:
新建 IcbcpayPaymentService
继承 AbstractPaymentService
覆写getIfCode()
函数: 并返回 icbcpay。
覆写isSupport()
函数: 对传入的wayCode进行判断是否支持。 支持返回true, 不支持返回false。
覆写preCheck()
函数: rq 和 payOrder信息进行预先校验, 如条码是否可用等。 返回错误信息,将进行api提示, 返回null表示验证通过,无错误。将继续执行。
覆写 pay()
函数: 根据rq 和 payOrder信息调起支付接口, 并返回包装响应数据。 如果payway比较多,建议在包下新建payway
, 然后调用: PaywayUtil.getRealPaywayService(this, payOrder.getWayCode()).pay(rq, payOrder, mchConfigContext);
对支付接口下的支付方式再次进行解耦。 可参考现有项目下的 alipay。
提示:
所有接口传入的
UnifiedOrderRQ rq
均可根据wayCode 强转为业务RQ, 用于读取到不同支付方式的传入信息;
比如: 支付宝bar支付:AliBarOrderRQ bizRQ = (AliBarOrderRQ) rq;
mchConfigContext 参数是当前支付商户的上下文信息, 包含商户的配置信息,商户服务商的配置信息等。
判断创建订单的商户是服务商特约商户还是普通商户:
mchConfigContext.isIsvsubMch()
获取服务商和特约商户配置参数 (定义参考2.2):
已支付宝为例
isv参数:
AlipayIsvParams isvParams = (AlipayIsvParams)configContextQueryService.queryIsvParams(mchAppConfigContext.getMchInfo().getIsvNo(), CS.IF_CODE.ALIPAY);
特约商户参数:
AlipayIsvsubMchParams isvsubMchParams = (AlipayIsvsubMchParams)configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), CS.IF_CODE.ALIPAY);
普通商户参数:
AlipayNormalMchParams mchParams = (AlipayNormalMchParams)configContextQueryService.queryNormalMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), CS.IF_CODE.ALIPAY);
获取回调接口地址:
getNotifyUrl()
获取同步跳转地址:
getReturnUrl()
获取上传的证书文件:
String isvPrivateCertFile = channelCertConfigKitBean.getCertFilePath(isvParams.getIsvPrivateCertFile());
构建支付响应数据:
// 构造函数响应数据 AliAppOrderRS res = ApiResBuilder.buildSuccess(AliAppOrderRS.class); ChannelRetMsg channelRetMsg = new ChannelRetMsg(); res.setChannelRetMsg(channelRetMsg); //放置 响应数据 channelRetMsg.setChannelAttach(payData); channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING); res.setPayData(payData);
ChannelRetMsg 为渠道侧的响应结果, 需要根据实际情况进行赋值操作:
订单状态 根据 上游渠道状态进行变更 如下:
明确成功 ==》 订单改为成功
明确失败 ==》 订单改为失败
等待 ==》 支付中 明确需要补单或者等待回调接口
未知 ==》 支付中 可能需要补单
接口报错 ==》 支付中 可能需要补单
系统异常 ==》 订单为: 订单生成状态。 --》 订单超时自动关闭。
b. 回调接口类:
新建 IcbcpayChannelNoticeService
继承 AbstractChannelNoticeService
覆写getIfCode()
函数: 并返回 icbcpay。
覆写parseParams()
函数: 用于处理渠道侧发送报文的解析, 并返回本支付系统订单号和自定义数据, 数据将向下传递。
覆写doNotice()
函数: 用于验签和处理响应结果。
提示:
parseParams函数返回类型MutablePair 为元组类型。 返回结果为: MutablePair<解析到的订单号,自定义数据>。
doNotice函数 需返回ChannelRetMsg 对象, 支持设置ChannelRetMsg中的 responseEntity , 将原样响应给上游。
获取支付参数和文件请参考支付接口。
ChannelRetMsg 信息尽量设置详细, 如上游订单号, 用户ID标识等。 订单状态为必须信息。 将更新返回结果更新订单状态。
c. 查单类:
新建 IcbcpayPayOrderQueryService
实现 IPayOrderQueryService
覆写getIfCode()
函数: 并返回 icbcpay。
覆写query()
函数: 请求渠道侧接口,并返回上游订单状态。
提示: query()函数需返回ChannelRetMsg对象, 参考支付接口或回调文档。
以上就完成了接口的对接工作, 给商户的支付通道配置好新对接的接口和费率进行测试工作吧。