ruoyi-vue-pro 添加三方支付(拉卡拉moss支付)

一、实现 PayClientConfig类

创建LklPayClientConfig配置类,存放拉卡拉支付的必须属性和实现支付client配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class LklPayClientConfig implements PayClientConfig{
/**
* 拉卡拉appId
*/
@NotBlank(message = "appId 不能为空")
protected String appId;
/**
* 商户证书序列号
*/
@NotBlank(message = "商户id")
protected String merchantId;
/**
* 商户私钥信息地址
*/
@NotBlank(message = "商户公钥 不能为空")
protected String merPubKey;
/**
* 拉卡拉支付平台证书(用于拉卡拉响应验签)
*/
@NotBlank(message = "商户私钥 不能为空")
protected String merPriKey;
/**
* 拉卡拉支付平台证书2(用于拉卡拉通知推送验签)
*/
@NotBlank(message = "平台公钥 不能为空")
protected String mossPubKey;

@Override
public void validate(Validator validator) {
// ValidationUtils.validate(validator, this,
// API_VERSION_V2.equals(this.getApiVersion()) ? V2.class : V3.class);
}
}

二、创建拉卡拉支付客户端抽象类

创建拉卡拉支付client抽象类,用于继承支付client和为拉卡拉支付client异化为pc,app和小程序各client做铺垫。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public abstract class AbstractLklPayClient extends AbstractPayClient<LklPayClientConfig> {

public AbstractLklPayClient(Long channelId, String channelCode, LklPayClientConfig config) {
super(channelId, channelCode, config);
}


@Override
protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Exception {
try {
return doUnifiedOrderV2(reqDTO);
} catch (WxPayException e) {
log.error("[doUnifiedOrder][支付({}) 发起拉卡拉支付异常", reqDTO, e);
String errorCode = getErrorCode(e);
String errorMessage = getErrorMessage(e);
return PayOrderRespDTO.closedOf(errorCode, errorMessage,
reqDTO.getOutTradeNo(), e.getXmlString());
}

/**
* 【V2】调用支付渠道,统一下单
*
* @param reqDTO 下单信息
* @return 各支付渠道的返回结果
*/
protected abstract PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO)
throws Exception;


/**
* 支付完成后的回调接口
* @param params 消息 params
* @param body 消息body
* @param headers 消息头
* @return 订单信息
* @throws Throwable
*/

@Override
public PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body, Map<String, String> headers) throws WxPayException {
return doParseOrderNotifyV2(body);
}

回调接口等暂未对接......

}

三、异化的不同客户端实现(以app client 为例)

实现支付、回调等接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
public class LklAppPayClient extends AbstractLklPayClient {

private final IMossApiService iMossApiService;
/**
* 付款码的过期时间
*/
private static final Duration AUTH_CODE_EXPIRE = Duration.ofMinutes(3);

public LklAppPayClient(Long channelId, LklPayClientConfig config) {
super(channelId, PayChannelEnum.LKL_APP.getCode(), config);
this.iMossApiService = new MossApiServiceImpl();
}
@Override
protected void doInit() {
// 拉卡拉支付不需要该初始化
// super.doInit();
}
@Override
protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) {
// 构建 request 对象
OrderPayReq request = new OrderPayReq();
// 商户订单号,32位,全局唯一,建议规则:businessChannel+日期时间+序列流水号
request.setOrder_no(reqDTO.getOutTradeNo());
// 订单总金额,分为单位,整数。示例:1元应填写 100
request.setTotal_amount(String.valueOf(reqDTO.getPrice().multiply(BigDecimal.valueOf(100)).intValue()));
// 商户号,平台客户下所发展的商户,通过MOSS平台新增商户产生,M+8位数字;
request.setMer_no(reqDTO.getChannelExtras().get("mer_no"));
// 订单备注信息
request.setRemark(reqDTO.getChannelExtras().get("remark"));
// 后端支付结果通知url,支付结果通知的平台后台回调地址,通知url必须为外网可访问的url,不能携带参数
request.setNotify_url(reqDTO.getNotifyUrl());
// 支付场景 0-标准收银台 1-独立支付API
request.setPay_scene("0");
// 钱包类型:
//pay_scene=0为非必传,可多传,表示为指定收银台内展示的支付方式;当pay_scene=1模式时必传单个支付方式。
//ALIPAY:支付宝
//WECHAT:微信
//UQRCODEPAY:银联云闪付
request.setAccount_type("ALIPAY,WECHAT,UQRCODEPAY");
// 订单标题,用于简单描述订单或商品主题。最多32个字符,如不送,默认显示商户简称
request.setSubject(reqDTO.getSubject());
// 订单有效期,格式yyyyMMddHHmmss,建议不超过15分钟。不传值则默认5分钟。
request.setOrder_eff_time(String.valueOf(2*60*60));
// 当客户微信公众号/支付宝生活号/云闪付H5支付场景时,拉起MOSS-H5收银台支付成功后,跳转至客户指定的URL页面地址;
request.setCallback_url("");
// 接入方式:
//41:NATIVE((ALIPAY,云闪付支持)
//51:JSAPI(微信公众号支付,支付宝服务窗支付,银联JS支付)
//71:微信小程序支付
// request.setTrans_type(reqDTO.getSubject());
// 地址位置信息,风控要求必送
// request.setLocation_info(reqDTO.getSubject());
// 用户在钱包侧唯一标识,微信支付宝侧为openid,云闪付为userid。trans_type为51情况下传入。
// request.setUser_id(reqDTO.getSubject());
// 账户端业务信息域,不同类型的account_type对应不同的账户端,需要填写以下不同的信息
// request.setAcc_busi_fields(reqDTO.getSubject());


// 获取信息
LklPayClientConfig config = getConfig();
request.setMerPriKey(config.getMerPriKey());
request.setMerPubKey(config.getMerPubKey());
request.setMossPubKey(config.getMossPubKey());
request.setBusinessChannel(config.getAppId());
request.setMer_no(config.getMerchantId());


// 执行请求,重试直到失败(过期),或者成功
ApiRes<OrderPayRes> response = iMossApiService.OrderPay(request);
return new PayOrderRespDTO().setDisplayContent(response.toString());
回调接口等暂未对接......
}
}