通道对接
通道对接
该文档适合技术人员阅读,可以帮助技术人员快速对接上游通道。我们这里将上游通道区分为支付通道和代付通道。
1. 支付通道
(1)支付流程
商户下单后,xxpay-pay项目中的PayOrderController类中的payOrder方法负责接收商户下单请求,该方法中会根据商户的下单请求参数,得到具体的支付通道名称,然后调用该通道的pay方法完成上游通道的下单操作,具体代码提下如下。
payOrderId = payOrder.getPayOrderId();
String channelId = payOrder.getChannelId();
String channelName = channelId.substring(0, channelId.indexOf("_"));
AbstractRes res = localDynamicChannelService.callPaymentMethod(channelName, payOrder, true);通过 localDynamicChannelService.callPaymentMethod(channelName, payOrder, true); 可以从spring容器中得到该通道的实例,然后调用具体的下单方法。
在命名通道类名的时候,格式须为:通道名称+PaymentService,如:AlipayPaymentService 为支付宝通道。
在XXPay4J中,已经支持内置支付通道和动态通道(可通过接口商店安装),具体代码逻辑参考类LocalDynamicChannelService 中的业务逻辑。
内置支付通道:指在xxpay-pay项目中硬编码实现,开发好需要部署class文件,重启项目。
动态支付通道:指动态开发的支付接口,打包成jar文件,在运营平台自动导入即可,项目可不用重启,直接可使用。
(2)内置支付通道实现
在xxpay-pay项目中的channel目录下,须为通道创建一个独立的目录。
比如这里以威富通为例,威富通就是一个具体的上游通道,给它定义名称为swiftpay,一般名字的定义来自通道的品牌名称。
然后在该目录下创建具体的支付实现类,名字为:SwiftpayPaymentService,类的名字必须是通道名称+PaymentService,首字母大写。然后该类继承自BasePayment,重写pay方法即可。
一般一个通道会对应多种支付方式,比如威富通会有微信扫码支付,支付宝扫码支付,统一条码支付等。那么每种支付方式需要对应一个支付接口,我们这样命名:通道名称+_+支付方式,如威富通微信扫码支付我们定义为:swiftpay_wxpay_native。
在pay方法中,我们会根据商户选择的支付方式,对应到上游通道的实现方法中,可以参考威富通的支付对接实现。具体的每种支付方式,需要参考上游通道的接口和demo来实现。
(3)通道支付回调
一般正规的支付流程,都是在用户支付成功后,上游通道会回调接口中上传的回调地址,那么我们需要处理上游过来的回调请求。
同样的,也是在支付通道目录下,创建一个支付回调的实现类,类的名字为:通道名称+PayNotifyService,如威富通支付的回调类名为:SwiftpayPayNotifyService,该类继承自BasePayNotify,重写doNotify方法即可。
在调用上游通道支付接口时,我们会指定回调地址,那么在我们系统中,通过统一的方式获取支付回调地址,具体代码如下。
// 前端页面跳转通知地址
paramMap.put("returnUrl", super.getReturnUrl(getChannelName(), dbConfig));
// 后台异步回调通知地址
paramMap.put("notifyUrl", super.getNotifyUrl(getChannelName(), dbConfig));notify地址格式为:http://支付系统地址/notify/通道名称/notify_res.htm,如威富通的回调地址为:http://pay.xx.com/notify/swiftpay/notify_res.htm,每个通道获取到的通知地址,通道名称是对应自己的。
通知的入口类为:NotifyPayController,实现代码为:
_log.info("====== 开始接收{}支付回调通知 ======", channel);
// 验证回调是否在白名单
String notifyIp = IPUtility.getClientIp(request);
String checkResult = notifyCheck(channel, notifyIp);
if (checkResult != null) return checkResult;
//获取通道对象示例
Object instance = localDynamicChannelService.getPayNotifyInterface(channel.toLowerCase());
if(instance instanceof PayNotifyInterface){
PayNotifyInterface payNotifyInterface = (PayNotifyInterface)instance;
if(payNotifyInterface == null){
return ApiBuilder.bizError("支付渠道类型[channel="+channel+"]实例化异常").toJSONString();
}
JSONObject retObj = payNotifyInterface.doNotify(request);
String notifyRes = retObj.getString(PayConstant.RESPONSE_RESULT);
_log.info("响应给{}:{}", channel, notifyRes);
_log.info("====== 完成接收{}支付回调通知 ======", channel);
return notifyRes;
}原理同支付下单流程类似,也是得到具体的通道,然后从spring容器中得到具体的通知实例,调用doNotify方法。
(4)通道参数定义
一般每个支付通道都会对应一些配置,比如商户ID,私钥,网关地址等信息。我们需要根据上游通道的接口文档,抽象出具体的配置字段,然后定义配置类。
一般类的名称命名为通道名称+Config,比如威富通的配置类为SwiftpayConfig。
威富通的配置包括:商户ID,商户key,网关请求地址,那么我们的代码是这样的。
public class SwiftpayConfig {
// 商户ID
private String mchId;
// 商户Key
private String key;
// 请求地址
private String reqUrl;
public SwiftpayConfig(){}
public SwiftpayConfig(String payParam) {
Assert.notNull(payParam, "init swiftpay config error");
JSONObject object = JSONObject.parseObject(payParam);
this.mchId = object.getString("mchId");
this.key = object.getString("key");
this.reqUrl = object.getString("reqUrl");
}
public String getMchId() {
return mchId;
}
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getReqUrl() {
return reqUrl;
}
public void setReqUrl(String reqUrl) {
this.reqUrl = reqUrl;
}
}在调用上游通道接口时,当需要使用配置参数时,我们可以这样使用。
SwiftpayConfig swiftpayConfig = new SwiftpayConfig(getPayParam(payOrder));
map.put("mch_id", swiftpayConfig.getMchId());(5)通道接口配置
以上支付通道的支付接口,回调接口都已经实现,这时需要在运营平台创建通道接口配置,才可使用。
创建支付接口类型
进入:运营平台 > 支付配置 > 支付接口类型 > 新增接口类型

- 接口类型代码:这个和支付通道的通道名称是一致的,如:swiftpay。
- 接口类型名称:对应上游支付通道名称,如:威富通支付。
- 配置定义描述:这里是和我们上面提到的通道配置类对应,内容为json格式,描述了生成该通道配置账户界面的表单内容。可使用官方工具生成:https://www.jeequan.com/dev/tool.html
- 回调IP白名单:如果配置了IP,那么只有该IP下的回调才会通过
- 订单超时时间:如果配置了,那么过了超时时间,系统会自动将订单关闭
创建支付接口
进入:运营平台 > 支付配置 > 支付接口 > 新增支付接口
- 接口代码:这里对应我们我们为每个支付通道定义的支付接口,如威富通的微信扫码支付,名字为:swiftpay_wxpay_native。
- 接口类型:选择对应的通道名称。
- 支付类型:根据具体的支付场景,选择对应的支付类型。
通道账号配置
进入:运营平台 > 支付配置 > 支付通道 > 子账户
账户配置的表单,就来自上面配置的支付接口类型的配置定义描述,也对应通道配置类中的属性。
2. 代付通道
代付通道的实现参考支付通道即可,这里调用的是上游的代付接口。下面给出几个核心逻辑类,相信聪明你的一定知道如何对接的。
代付下单入口类:AgentpayController
转账实现类名称格式:通道名称+TransService,重写trans方法。
转账判断是否成功很关键,一定要在明确成功或失败时,才可以设置代付最终业务结果。
对接上游通道代付接口时,如果判断代付接口,一般有三种方式:
- 调代付接口直接同步响应结果,明确告诉代付已经成功,该种最简单直接处理业务即可。
- 调代付接口时,上游通道同步返回申请成功,需要主动查询代付结果。在我们系统,可通过如下代码实现。
// 交易处理中
_log.info("{} >>> 转账处理中", logPrefix);
JSONObject msgObj = new JSONObject();
msgObj.put("count", 1);
msgObj.put("transOrderId", transOrderId);
msgObj.put("channelName", getChannelName());
mq4TransQuery.send(msgObj.toJSONString(), 10 * 1000); // 10秒后查询
return QueryRetMsg.waiting();通过mq方式,设置延迟查询,直到查询到成功或失败。可参考项目中杉德代付的代码:`SandpayTransService`。
- 调代付接口时,上游通道同步返回申请成功,需要接收上游通道的异步回调,确认代付结果。在我们系统中,需要实现回调方法接口。
增加回调处理类,名称格式为:通道名称 + TransNotifyService,重写doNotify方法。可参考项目中双乾代付的代码:SqpayTransNotifyService。
如果还是搞不定,可以联系售后技术支持哦!