jeepay支付系统开源版 已完成了如下接口的对接工作:

  • 支付宝官方普通商户模式/ isv模式 (RSA / RSA2加密 / 证书加密)

  • 微信官方普通商户/服务商模式 (V2 / V3接口)

  • 云闪付开放平台服务商模式

若您有更多的三方/银行接口 需要对接联调请参考以下文档进行二次开发,也可以联系官方技术收费开发(QQ:13527422)。

一、 接口准备工作:

1.1 > 接口起名:

按照jeepay项目的约定: 所有支付接口需全部小写,并且以pay结尾, 例如 alipay, wxpay, ysfpay

比方我们待对接的通道为工行支付,起名 icbcpay, 以下文档按照icbcpay进行说明。

1.2 > 准备三方支付接口:

  1. 支付下单接口;

  2. 回调通知接口;

  3. 订单查询接口;

  4. 获取三方用户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>. 页面操作如图:

注意:

  1. if_code字段为小写。

  2. 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_CODEPAY_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.pay.rqrs.payorder.payway 中进行定义。

ICBC_APP为例:

a. 新建 IcbcAppOrderRQ 继承 UnifiedOrderRQ

构造函数中将wayCode传入为 ICBC_APP 支付方式。  支持自定义字段,下单时可根据该支付方式进行传参。  

新建RQ后需要同步在: com.jeequan.jeepay.pay.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.pay.channel 包下定义好对应的接口, 根据不同业务实现不同的接口即可。

说明:

IChannelUserService : 获取渠道用户ID的接口定义

IPaymentService : 调起渠道侧下单支付接口定义

IPayNotifyService : 渠道回调通知解析数据定义

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.pay.channel 下新建 icbcpay 包: com.jeequan.jeepay.pay.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。

提示:

  1. 所有接口传入的 UnifiedOrderRQ rq 均可根据wayCode 强转为业务RQ, 用于读取到不同支付方式的传入信息;
    比如: 支付宝bar支付: AliBarOrderRQ bizRQ = (AliBarOrderRQ) rq;

  2. mchConfigContext 参数是当前支付商户的上下文信息, 包含商户的配置信息,商户服务商的配置信息等。

  3. 判断创建订单的商户是服务商特约商户还是普通商户: mchConfigContext.isIsvsubMch()

  4. 获取服务商和特约商户配置参数 (定义参考2.2):

    已支付宝为例


    isv参数: AlipayIsvParams isvParams = mchConfigContext.getIsvConfigContext().getIsvParamsByIfCode(getIfCode(), AlipayIsvParams.class);

    特约商户参数: AlipayIsvsubMchParams isvsubMchParams = mchConfigContext.getIsvsubMchParamsByIfCode(getIfCode(), AlipayIsvsubMchParams.class);


    普通商户参数: AlipayNormalMchParams normalMchParams = mchConfigContext.getNormalMchParamsByIfCode(getIfCode(), AlipayNormalMchParams.class);


  5. 获取回调接口地址: getNotifyUrl()

  6. 获取同步跳转地址: getReturnUrl()

  7. 获取上传的证书文件: channelCertConfigKitBean.getCertFilePath(isvParams.getIsvPrivateCertFile())

  8. 构建支付响应数据:

      // 构造函数响应数据
     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. 回调接口类:

新建 IcbcpayPayNotifyService 继承 AbstractPayNotifyService

覆写getIfCode()函数: 并返回 icbcpay。

覆写parseParams()函数: 用于处理渠道侧发送报文的解析, 并返回本支付系统订单号和自定义数据, 数据将向下传递。

覆写payNotify()函数: 用于验签和处理响应结果。

提示:

  1. parseParams函数返回类型MutablePair 为元组类型。 返回结果为: MutablePair<解析到的订单号,自定义数据>。

  2. payNotify函数 需返回ChannelRetMsg 对象, 支持设置ChannelRetMsg中的 responseEntity , 将原样响应给上游。
    获取支付参数和文件请参考支付接口。
    ChannelRetMsg 信息尽量设置详细, 如上游订单号, 用户ID标识等。 订单状态为必须信息。 将更新返回结果更新订单状态。

c. 查单类:

新建 IcbcpayPayOrderQueryService 实现 IPayOrderQueryService

覆写getIfCode()函数: 并返回 icbcpay。

覆写query()函数: 请求渠道侧接口,并返回上游订单状态。

提示: query()函数需返回ChannelRetMsg对象, 参考支付接口或回调文档。


以上就完成了接口的对接工作, 给商户的支付通道配置好新对接的接口和费率进行测试工作吧。

文档更新时间: 2021-06-28 17:21   作者:大森林