提交
This commit is contained in:
257
jeepay-components/jeepay-components-3rd/pom.xml
Normal file
257
jeepay-components/jeepay-components-3rd/pom.xml
Normal file
@@ -0,0 +1,257 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion> <!-- POM模型版本 -->
|
||||
|
||||
<groupId>com.jeequan</groupId> <!-- 组织名, 类似于包名 -->
|
||||
<artifactId>jeepay-components-3rd</artifactId> <!-- 项目名称 -->
|
||||
<packaging>jar</packaging> <!-- 项目的最终打包类型/发布形式, 可选[jar, war, pom, maven-plugin]等 -->
|
||||
<version>${isys.version}</version> <!-- 项目当前版本号 -->
|
||||
<description>Jeepay计全支付系统 [三方调用接口]</description> <!-- 项目描述 -->
|
||||
<url>https://www.jeequan.com</url>
|
||||
|
||||
<parent>
|
||||
<groupId>com.jeequan</groupId>
|
||||
<artifactId>jeepay-components</artifactId>
|
||||
<version>Final</version>
|
||||
</parent>
|
||||
|
||||
<!-- 项目属性 -->
|
||||
<properties>
|
||||
<projectRootDir>${basedir}/../../</projectRootDir>
|
||||
</properties>
|
||||
|
||||
<!-- 项目依赖声明 -->
|
||||
<dependencies>
|
||||
|
||||
<!-- 依赖[ service ]包 (仅查询参数配置即可, 业务的处理不应该在该层进行 ) -->
|
||||
<dependency>
|
||||
<groupId>com.jeequan</groupId>
|
||||
<artifactId>jeepay-components-db</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.bill99</groupId>
|
||||
<artifactId>crypto-sdk</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 依赖[ oss ]包 -->
|
||||
<dependency>
|
||||
<groupId>com.jeequan</groupId>
|
||||
<artifactId>jeepay-components-oss</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.coobird</groupId>
|
||||
<artifactId>thumbnailator</artifactId>
|
||||
<version>0.4.14</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 依赖 sping-boot-web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 可选依赖 [spring-redis] -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- hibernate.validator插件 -->
|
||||
<dependency>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--wx_pay https://github.com/wechat-group/WxJava -->
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-pay</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-mp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-miniapp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- adapay -->
|
||||
<!-- https://mvnrepository.com/artifact/com.huifu.adapay.core/adapay-core-sdk -->
|
||||
<dependency>
|
||||
<groupId>com.huifu.adapay.core</groupId>
|
||||
<artifactId>adapay-core-sdk</artifactId>
|
||||
<version>1.2.10</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.huifu.adapay/adapay-java-sdk -->
|
||||
<dependency>
|
||||
<groupId>com.huifu.adapay</groupId>
|
||||
<artifactId>adapay-java-sdk</artifactId>
|
||||
<version>1.2.10</version>
|
||||
</dependency>
|
||||
|
||||
<!-- paypal 支付 -->
|
||||
<dependency>
|
||||
<groupId>com.paypal.sdk</groupId>
|
||||
<artifactId>checkout-sdk</artifactId>
|
||||
<version>1.0.5</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 生成二维码工具包 zxing -->
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>javase</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java -->
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- mqtt 智谷物联使用mqtt连接 -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.paho</groupId>
|
||||
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||
<version>1.2.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里云OCR -->
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>ocr_api20210707</artifactId>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 腾讯云OCR -->
|
||||
<dependency>
|
||||
<groupId>com.tencentcloudapi</groupId>
|
||||
<artifactId>tencentcloud-sdk-java</artifactId>
|
||||
<version>3.1.322</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 个推 消息推送 -->
|
||||
<dependency>
|
||||
<groupId>com.getui.push</groupId>
|
||||
<artifactId>restful-sdk</artifactId>
|
||||
<version>1.0.0.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 杉德的河马付依赖包 -->
|
||||
<dependency>
|
||||
<groupId>cn.com.sand</groupId>
|
||||
<artifactId>sandpay-hmpay-sdk</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 富友FTP SFTP依赖包 -->
|
||||
<dependency>
|
||||
<groupId>commons-net</groupId>
|
||||
<artifactId>commons-net</artifactId>
|
||||
<version>3.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
<version>0.1.54</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 银盛支付sdk -->
|
||||
<dependency>
|
||||
<groupId>cfca.sadk</groupId>
|
||||
<artifactId>cfca-sadk</artifactId>
|
||||
</dependency>
|
||||
<!-- 银盛支付sdk -->
|
||||
<dependency>
|
||||
<groupId>cfca.logback</groupId>
|
||||
<artifactId>cfca-logback</artifactId>
|
||||
</dependency>
|
||||
<!-- 银盛支付sdk -->
|
||||
<dependency>
|
||||
<groupId>hikefa.core</groupId>
|
||||
<artifactId>yspay-hikefa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 国密算法 BC库依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<version>1.61</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.payermax</groupId>
|
||||
<artifactId>payermax-server-sdk</artifactId>
|
||||
<version>1.0.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 建行龙支付SDK -->
|
||||
<dependency>
|
||||
<groupId>ccbpay.netpay</groupId>
|
||||
<artifactId>ccbpay-netpay</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 支付宝云支付 -->
|
||||
<dependency>
|
||||
<groupId>com.alipay.bpaas</groupId>
|
||||
<artifactId>bpaas-bizapi-sdk</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 交行支付SDK -->
|
||||
<dependency>
|
||||
<groupId>com.bocom.api</groupId>
|
||||
<artifactId>bocom-openapi-sdk</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 工行支付SDK -->
|
||||
<dependency>
|
||||
<groupId>com.icbc</groupId>
|
||||
<artifactId>icbc-api-sdk-cop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.icbc.api</groupId>
|
||||
<artifactId>icbc-api-sdk-cop-io</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.com.infosec</groupId>
|
||||
<artifactId>icbc-ca</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.icbc</groupId>
|
||||
<artifactId>hsm-software-share</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.clj</groupId>
|
||||
<artifactId>leshuapay-sdk</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jeequan</groupId>
|
||||
<artifactId>jeepay-components-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchWrapper;
|
||||
import com.jeequan.jeepay.core.model.applyment.ApplymentBasicInfo;
|
||||
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
|
||||
import com.jeequan.jeepay.db.entity.MchAppEntity;
|
||||
import com.jeequan.jeepay.db.entity.RateConfig;
|
||||
import com.jeequan.jeepay.service.impl.MchAppService;
|
||||
import com.jeequan.jeepay.service.impl.RateConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class AbsIsvmchWrapper<T extends ApplymentBasicInfo> implements IIsvmchWrapper {
|
||||
|
||||
@Autowired
|
||||
private RateConfigService rateConfigService;
|
||||
|
||||
@Autowired
|
||||
private MchAppService mchAppService;
|
||||
|
||||
/**
|
||||
* 根据商户的上下级设置其缺省的费率值
|
||||
*
|
||||
* @param mchApplyment 商户信息
|
||||
*/
|
||||
@Override
|
||||
public final void rateWrap(MchApplyment mchApplyment) {
|
||||
JSONObject applyDetailInfo = JSON.parseObject(mchApplyment.getApplyDetailInfo());
|
||||
|
||||
Map<String, PaywayFee> mchApplyRateConfigMap = new HashMap<>();
|
||||
Optional.ofNullable(applyDetailInfo.getJSONArray("paywayFeeList"))
|
||||
.map(t -> t.toJavaList(PaywayFee.class))
|
||||
.map(t -> {
|
||||
t.forEach(t2 -> mchApplyRateConfigMap.put(t2.getWayCode(), t2));
|
||||
return t;
|
||||
});
|
||||
|
||||
MchAppEntity mchApp = mchAppService.getById(mchApplyment.getAutoConfigMchAppId());
|
||||
|
||||
String agentNo = mchApplyment.getAgentNo();
|
||||
String isvNo = mchApplyment.getIsvNo();
|
||||
|
||||
// 获取商户费率, 一般来说这一步是没必要的,这里单纯做数据初始化吧
|
||||
Map<String, PaywayFee> mchRateConfigMap = rateConfigService.queryPaywayFeeMap(agentNo + "_" + RateConfig.MCHRATE, CS.SYS_ROLE_TYPE.MCH_APP, mchApplyment.getIfCode()
|
||||
, mchApp.getRange(), mchApp.getMccCode(), mchApplyment.getIsvNo());
|
||||
setIfEmpty(mchApplyRateConfigMap, mchRateConfigMap);
|
||||
|
||||
// 获取直属上级费率
|
||||
Map<String, PaywayFee> agentMchDefRateConfigMap = rateConfigService.queryPaywayFeeMap(agentNo + "_" + RateConfig.MCHAPPLYDEF, CS.SYS_ROLE_TYPE.AGENT, mchApplyment.getIfCode()
|
||||
, mchApp.getRange(), mchApp.getMccCode(), mchApplyment.getIsvNo());
|
||||
setIfEmpty(mchRateConfigMap, agentMchDefRateConfigMap);
|
||||
|
||||
// 获取服务商费率信息
|
||||
Map<String, PaywayFee> isvRateConfigMap = rateConfigService.queryPaywayFeeMap(isvNo + "_" + RateConfig.MCHAPPLYDEF, CS.SYS_ROLE_TYPE.ISV, mchApplyment.getIfCode()
|
||||
, mchApp.getRange(), mchApp.getMccCode(), mchApplyment.getIsvNo());
|
||||
setIfEmpty(mchRateConfigMap, isvRateConfigMap);
|
||||
|
||||
mchRateConfigMap = channelInit(mchRateConfigMap, mchApplyment);
|
||||
|
||||
applyDetailInfo.put("paywayFeeList", mchRateConfigMap.values());
|
||||
|
||||
mchApplyment.setApplyDetailInfo(JSON.toJSONString(applyDetailInfo));
|
||||
}
|
||||
|
||||
private void setIfEmpty(Map<String, PaywayFee> mchRate, Map<String, PaywayFee> targetConfigMap) {
|
||||
targetConfigMap.forEach((wayCode, rateConfig) -> mchRate.putIfAbsent(wayCode, targetConfigMap.get(wayCode)));
|
||||
}
|
||||
|
||||
public Map<String, PaywayFee> channelInit(Map<String, PaywayFee> mchRateConfigMap, MchApplyment mchApplyment) {
|
||||
return mchRateConfigMap;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.jeequan.jeepay.components.oss.ctrl.OssFileController;
|
||||
import com.jeequan.jeepay.components.oss.model.MockMultipartFile;
|
||||
import com.jeequan.jeepay.components.oss.model.OssFileConfig;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.CheckBatch;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IBillDownloadService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/*
|
||||
* 渠道对账单下载 抽象类
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2021/6/8 17:18
|
||||
*/
|
||||
public abstract class AbstractBillDownloadService implements IBillDownloadService {
|
||||
|
||||
@Autowired protected SysConfigService sysConfigService;
|
||||
@Autowired protected ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
@Autowired private OssFileController ossFileController;
|
||||
|
||||
|
||||
// 上传文件至oss
|
||||
public String upload2Oss(String ifCode, String channelMchNo, Date billDate, String suffix, InputStream inputStream){
|
||||
return ossFileController.singleFileUpload(new MockMultipartFile(genOssFileName(ifCode, channelMchNo, billDate, suffix), 1L, inputStream), OssFileConfig.BIZ_TYPE.CHANNEL_BILL);
|
||||
}
|
||||
|
||||
// 生成上传oss 账单文件名称、后缀
|
||||
public String genOssFileName(String ifCode, String channelMchNo, Date billDate, String suffix){
|
||||
return String.format("%s_%s_%s_%s", ifCode, channelMchNo, DateUtil.format(billDate, DatePattern.PURE_DATE_PATTERN), suffix);
|
||||
}
|
||||
|
||||
/** 生成渠道账单 解析成功 的对账批次 */
|
||||
public CheckBatch genReleaseSuccessCheckBatch(String ifCode, Date billDate, String channelMchNo, String path) {
|
||||
return initCheckBatch(ifCode, billDate, channelMchNo, path, CS.YES, null);
|
||||
}
|
||||
|
||||
/** 生成渠道账单 解析失败 的对账批次 */
|
||||
public CheckBatch genReleaseFailCheckBatch(String ifCode, Date billDate, String channelMchNo, String releaseErrMsg) {
|
||||
return initCheckBatch(ifCode, billDate, channelMchNo, null, CS.NO, releaseErrMsg);
|
||||
}
|
||||
|
||||
/** 初始化对账批次 */
|
||||
public CheckBatch initCheckBatch(String ifCode, Date billDate, String channelMchNo, String path, Byte releaseState, String releaseErrMsg) {
|
||||
CheckBatch checkBatch = new CheckBatch();
|
||||
checkBatch.setBatchNo(getBatchNo(ifCode, channelMchNo, billDate));
|
||||
checkBatch.setIfCode(ifCode);
|
||||
checkBatch.setBillDate(billDate);
|
||||
checkBatch.setChannelMchNo(channelMchNo);
|
||||
checkBatch.setState(CS.NO); //未处理状态
|
||||
checkBatch.setOrgBillFilePath(path);
|
||||
checkBatch.setReleaseState(releaseState);
|
||||
checkBatch.setReleaseErrMsg(releaseErrMsg);
|
||||
checkBatch.setChannelTotalAmount(BigDecimal.ZERO.longValue());
|
||||
return checkBatch;
|
||||
}
|
||||
|
||||
// 对账批次号 支付接口代码ifCode_渠道商户号_对账日期
|
||||
public String getBatchNo(String ifCode, String channelMchNo, Date billDate) {
|
||||
return ifCode + "_" + channelMchNo + "_" + DateUtil.format(billDate, DatePattern.PURE_DATE_PATTERN);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IChannelAccountService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/*
|
||||
* 提现接口抽象类
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2021/6/8 17:18
|
||||
*/
|
||||
public abstract class AbstractChannelAccountService implements IChannelAccountService {
|
||||
|
||||
@Autowired protected SysConfigService sysConfigService;
|
||||
@Autowired protected ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
|
||||
|
||||
protected String getPaySiteUrl() {
|
||||
return sysConfigService.getDBApplicationConfig().getPaySiteUrl();
|
||||
}
|
||||
|
||||
protected String getNotifyUrl(){
|
||||
return getPaySiteUrl() + "/api/channel/cashout/notify/" + getIfCode();
|
||||
}
|
||||
|
||||
protected String getNotifyUrl(String rid){
|
||||
return getPaySiteUrl() + "/api/channel/cashout/notify/" + getIfCode() + "/" + rid;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.beans.RequestKitBean;
|
||||
import com.jeequan.jeepay.core.interfaces.cashout.IChannelCashoutNoticeService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/*
|
||||
* 实现提现回调接口抽象类
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2021/6/8 17:18
|
||||
*/
|
||||
public abstract class AbstractChannelCashoutNoticeService implements IChannelCashoutNoticeService {
|
||||
|
||||
@Autowired private RequestKitBean requestKitBean;
|
||||
@Autowired private ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
|
||||
/** 文本类型的响应数据 **/
|
||||
protected ResponseEntity textResp(String text){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.TEXT_HTML);
|
||||
return new ResponseEntity(text, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/** json类型的响应数据 **/
|
||||
protected ResponseEntity jsonResp(Object body){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
return new ResponseEntity(body, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected JSONObject getReqParamJSON() {
|
||||
return requestKitBean.getReqParamJSON();
|
||||
}
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected String getReqParamFromBody() {
|
||||
return requestKitBean.getReqParamFromBody();
|
||||
}
|
||||
|
||||
/** 获取文件路径 **/
|
||||
protected String getCertFilePath(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFilePath(certFilePath);
|
||||
}
|
||||
|
||||
/** 获取文件File对象 **/
|
||||
protected File getCertFile(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFile(certFilePath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.beans.RequestKitBean;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IChannelNoticeService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
|
||||
/*
|
||||
* 实现回调接口抽象类
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:18
|
||||
*/
|
||||
public abstract class AbstractChannelNoticeService implements IChannelNoticeService {
|
||||
|
||||
@Autowired private RequestKitBean requestKitBean;
|
||||
@Autowired private ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public ResponseEntity doNotifyOrderNotExists(HttpServletRequest request) {
|
||||
return textResp("order not exists");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity doNotifyOrderStateUpdateFail(HttpServletRequest request) {
|
||||
return textResp("update status error");
|
||||
}
|
||||
|
||||
/** 文本类型的响应数据 **/
|
||||
protected ResponseEntity textResp(String text){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.TEXT_HTML);
|
||||
return new ResponseEntity(text, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/** json类型的响应数据 **/
|
||||
protected ResponseEntity jsonResp(Object body){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
return new ResponseEntity(body, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected JSONObject getReqParamJSON() {
|
||||
return requestKitBean.getReqParamJSON();
|
||||
}
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected String getReqParamFromBody() {
|
||||
return requestKitBean.getReqParamFromBody();
|
||||
}
|
||||
|
||||
/** 获取文件路径 **/
|
||||
protected String getCertFilePath(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFilePath(certFilePath);
|
||||
}
|
||||
|
||||
/** 获取文件File对象 **/
|
||||
protected File getCertFile(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFile(certFilePath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.beans.RequestKitBean;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IChannelOrderAcceptService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/*
|
||||
* 实现回调接口抽象类
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:18
|
||||
*/
|
||||
public abstract class AbstractChannelOrderAcceptService implements IChannelOrderAcceptService {
|
||||
|
||||
@Autowired private RequestKitBean requestKitBean;
|
||||
@Autowired private ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
|
||||
|
||||
/** 文本类型的响应数据 **/
|
||||
protected ResponseEntity textResp(String text){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.TEXT_HTML);
|
||||
return new ResponseEntity(text, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/** json类型的响应数据 **/
|
||||
protected ResponseEntity jsonResp(Object body){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
return new ResponseEntity(body, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected JSONObject getReqParamJSON() {
|
||||
return requestKitBean.getReqParamJSON();
|
||||
}
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected String getReqParamFromBody() {
|
||||
return requestKitBean.getReqParamFromBody();
|
||||
}
|
||||
|
||||
/** 获取文件路径 **/
|
||||
protected String getCertFilePath(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFilePath(certFilePath);
|
||||
}
|
||||
|
||||
/** 获取文件File对象 **/
|
||||
protected File getCertFile(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFile(certFilePath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.beans.RequestKitBean;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IChannelRefundNoticeService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
|
||||
/*
|
||||
* 实现退款回调接口抽象类
|
||||
*
|
||||
* @author jmdhappy
|
||||
*
|
||||
* @date 2021/9/25 23:18
|
||||
*/
|
||||
public abstract class AbstractChannelRefundNoticeService implements IChannelRefundNoticeService {
|
||||
|
||||
@Autowired private RequestKitBean requestKitBean;
|
||||
@Autowired private ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public ResponseEntity doNotifyOrderNotExists(HttpServletRequest request) {
|
||||
return textResp("order not exists");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity doNotifyOrderStateUpdateFail(HttpServletRequest request) {
|
||||
return textResp("update status error");
|
||||
}
|
||||
|
||||
/** 文本类型的响应数据 **/
|
||||
protected ResponseEntity textResp(String text){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.TEXT_HTML);
|
||||
return new ResponseEntity(text, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/** json类型的响应数据 **/
|
||||
protected ResponseEntity jsonResp(Object body){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
return new ResponseEntity(body, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected JSONObject getReqParamJSON() {
|
||||
return requestKitBean.getReqParamJSON();
|
||||
}
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected String getReqParamFromBody() {
|
||||
return requestKitBean.getReqParamFromBody();
|
||||
}
|
||||
|
||||
/** 获取文件路径 **/
|
||||
protected String getCertFilePath(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFilePath(certFilePath);
|
||||
}
|
||||
|
||||
/** 获取文件File对象 **/
|
||||
protected File getCertFile(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFile(certFilePath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.beans.RequestKitBean;
|
||||
import com.jeequan.jeepay.core.entity.PayOrderDivisionRecord;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.DivisionChannelNotifyModel;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* 分账结果回调接口抽象类
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2023/3/29 15:39
|
||||
*/
|
||||
public abstract class AbstractDivisionRecordChannelNotifyService {
|
||||
|
||||
@Autowired private RequestKitBean requestKitBean;
|
||||
@Autowired private ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
|
||||
|
||||
/** 获取到接口code **/
|
||||
public abstract String getIfCode();
|
||||
|
||||
/** 解析参数: 批次号 和 请求参数
|
||||
* 异常需要自行捕捉,并返回null , 表示已响应数据。
|
||||
* **/
|
||||
public abstract MutablePair<String, Object> parseParams(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 返回需要更新的记录 <ID, 结果> 状态 和响应数据
|
||||
*
|
||||
* **/
|
||||
public abstract DivisionChannelNotifyModel doNotify(HttpServletRequest request, Object params,
|
||||
List<? extends PayOrderDivisionRecord> recordList, MchAppConfigContext mchAppConfigContext);
|
||||
|
||||
public ResponseEntity doNotifyOrderNotExists(HttpServletRequest request) {
|
||||
return textResp("order not exists");
|
||||
}
|
||||
|
||||
public ResponseEntity doNotifyOrderStateUpdateFail(HttpServletRequest request) {
|
||||
return textResp("update status error");
|
||||
}
|
||||
|
||||
/** 文本类型的响应数据 **/
|
||||
protected ResponseEntity textResp(String text){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.TEXT_HTML);
|
||||
return new ResponseEntity(text, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/** json类型的响应数据 **/
|
||||
protected ResponseEntity jsonResp(Object body){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
return new ResponseEntity(body, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected JSONObject getReqParamJSON() {
|
||||
return requestKitBean.getReqParamJSON();
|
||||
}
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected String getReqParamFromBody() {
|
||||
return requestKitBean.getReqParamFromBody();
|
||||
}
|
||||
|
||||
/** 获取文件路径 **/
|
||||
protected String getCertFilePath(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFilePath(certFilePath);
|
||||
}
|
||||
|
||||
/** 获取文件File对象 **/
|
||||
protected File getCertFile(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFile(certFilePath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
|
||||
import com.jeequan.jeepay.core.entity.*;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IDivisionService;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* abstract 分账实现
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2022/6/13 11:09
|
||||
*/
|
||||
public abstract class AbstractDivisionService implements IDivisionService {
|
||||
|
||||
@Autowired
|
||||
protected SysConfigService sysConfigService;
|
||||
|
||||
protected String getPaySiteUrl() {
|
||||
return sysConfigService.getDBApplicationConfig().getPaySiteUrl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIfCode(MchDivisionReceiver mchDivisionReceiver) {
|
||||
return mchDivisionReceiver.getIfCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIfCode(PayOrder payOrder) {
|
||||
return payOrder.getIfCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIfCode(PayOrderDivisionRecord payOrderDivisionRecord) {
|
||||
return payOrderDivisionRecord.getIfCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean divisionRefundIsOrderRefundAfterProc() {
|
||||
return false; // 默认分账业务前发起退分处理。
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<Long, ChannelRetMsg> queryDivision(PayOrder payOrder, List<? extends PayOrderDivisionRecord> recordList, MchAppConfigContext mchAppConfigContext){
|
||||
throw new BizException("接口不支持");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg divisionRefund(PayOrderDivisionRecord payOrderDivisionRecord, PayOrderDivisionRefundRecord payOrderDivisionRefundRecord, RefundOrder refundOrder, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) {
|
||||
throw new BizException("接口不支持");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long queryBalanceAmount(MchDivisionReceiver mchDivisionReceiver, MchAppConfigContext mchAppConfigContext) {
|
||||
throw new BizException("接口不支持");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg cashout(MchDivisionReceiver mchDivisionReceiver, Long amount, MchAppConfigContext mchAppConfigContext) {
|
||||
throw new BizException("接口不支持");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String divisionFinishAfterDivision(PayOrderDivisionRecord divisionRecord, MchAppConfigContext mchAppConfigContext) {
|
||||
throw new BizException("接口不支持");
|
||||
}
|
||||
|
||||
protected String getNotifyUrl(){
|
||||
return getPaySiteUrl() + "/api/divisionRecordChannelNotify/" + getIfCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IMchApiService;
|
||||
import com.jeequan.jeepay.core.model.params.IsvParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.settle.ChannelSettleRq;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @author crystal
|
||||
* @date 2023/12/4 10:46
|
||||
*/
|
||||
public abstract class AbstractMchApiService<T extends IsvParams> implements IMchApiService<T> {
|
||||
|
||||
/**
|
||||
* 通用结算参数校验
|
||||
* @param settleRq
|
||||
*/
|
||||
protected void preSettleCheck(ChannelSettleRq settleRq){
|
||||
if(settleRq.getPage() == null){
|
||||
throw new BizException("当前页不能为空");
|
||||
}
|
||||
if(settleRq.getSize() == null){
|
||||
throw new BizException("每页显示的条数不能为空");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.beans.RequestKitBean;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchStoreApplymentNotifyService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* 实现回调接口抽象类
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/3/26 18:21
|
||||
*/
|
||||
public abstract class AbstractMchApplymentNoticeService implements IIsvmchStoreApplymentNotifyService {
|
||||
|
||||
@Autowired private RequestKitBean requestKitBean;
|
||||
@Autowired private ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
|
||||
/** 文本类型的响应数据 **/
|
||||
protected ResponseEntity textResp(String text){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.TEXT_HTML);
|
||||
return new ResponseEntity(text, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/** json类型的响应数据 **/
|
||||
protected ResponseEntity jsonResp(Object body){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
return new ResponseEntity(body, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected JSONObject getReqParamJSON() {
|
||||
return requestKitBean.getReqParamJSON();
|
||||
}
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected String getReqParamFromBody() {
|
||||
return requestKitBean.getReqParamFromBody();
|
||||
}
|
||||
|
||||
/** 获取文件路径 **/
|
||||
protected String getCertFilePath(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFilePath(certFilePath);
|
||||
}
|
||||
|
||||
/** 获取文件File对象 **/
|
||||
protected File getCertFile(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFile(certFilePath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IPaymentService;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.terminal.TerminalChannelModel;
|
||||
import com.jeequan.jeepay.db.entity.MchStoreTerminal;
|
||||
import com.jeequan.jeepay.service.impl.MchStoreTerminalService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/*
|
||||
* 支付接口抽象类
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:18
|
||||
*/
|
||||
public abstract class AbstractPaymentService implements IPaymentService {
|
||||
|
||||
@Autowired protected SysConfigService sysConfigService;
|
||||
@Autowired protected ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
@Autowired private MchStoreTerminalService mchStoreTerminalService;
|
||||
|
||||
@Override
|
||||
public String getIfCode(PayOrder payOrder) {
|
||||
return payOrder.getIfCode();
|
||||
}
|
||||
|
||||
/** 订单分账(一般用作 如微信订单将在下单处做标记) */
|
||||
protected boolean isDivisionOrder(PayOrder payOrder){
|
||||
//订单分账, 将冻结商户资金。
|
||||
if(payOrder.getDivisionMode() != null && (PayOrder.DIVISION_MODE_AUTO == payOrder.getDivisionMode() || PayOrder.DIVISION_MODE_MANUAL == payOrder.getDivisionMode() )){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String getPaySiteUrl() {
|
||||
return sysConfigService.getDBApplicationConfig().getPaySiteUrl();
|
||||
}
|
||||
|
||||
protected String getNotifyUrl(){
|
||||
return getPaySiteUrl() + "/api/pay/notify/" + getIfCode();
|
||||
}
|
||||
|
||||
protected String getNotifyUrl(String payOrderId){
|
||||
return getPaySiteUrl() + "/api/pay/notify/" + getIfCode() + "/" + payOrderId;
|
||||
}
|
||||
|
||||
protected String getNotifyUrlByFixMchApp(String mchAppId){
|
||||
return getPaySiteUrl() + "/api/pay/notify/" + getIfCode() + "/" + CS.PAY_RETURNURL_FIX_MCHAPP_PREFIX + mchAppId;
|
||||
}
|
||||
|
||||
protected String getPosNotifyUrl(){
|
||||
return getPaySiteUrl() + "/api/pos/pay/notify/" + getIfCode();
|
||||
}
|
||||
|
||||
protected String getReturnUrl(){
|
||||
return getPaySiteUrl() + "/api/pay/return/" + getIfCode();
|
||||
}
|
||||
|
||||
protected String getReturnUrl(String payOrderId){
|
||||
return sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/pay/return/" + getIfCode() + "/" + payOrderId;
|
||||
}
|
||||
|
||||
protected String getReturnUrlOnlyJump(String payOrderId){
|
||||
return getPaySiteUrl() + "/api/pay/return/" + getIfCode() + "/" + CS.PAY_RETURNURL_FIX_ONLY_JUMP_PREFIX + payOrderId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查找出对应的设备信息
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2022/4/29 15:20
|
||||
*/
|
||||
protected String queryStoreTerminalChannelTrmNo(String trmNo, PayOrder payOrder){
|
||||
|
||||
MchStoreTerminal mchStoreTerminal = null;
|
||||
|
||||
LambdaQueryWrapper<MchStoreTerminal> lambdaQueryWrapper = MchStoreTerminal.gw()
|
||||
.eq(MchStoreTerminal::getMchNo, payOrder.getMchNo())
|
||||
.eq(MchStoreTerminal::getAppId, payOrder.getAppId())
|
||||
.eq(MchStoreTerminal::getStoreId, payOrder.getStoreId())
|
||||
.eq(MchStoreTerminal::getState, CS.YES);
|
||||
|
||||
// 指定编号查询
|
||||
if(StringUtils.isNotEmpty(trmNo)){
|
||||
|
||||
lambdaQueryWrapper.eq(MchStoreTerminal::getTrmNo, trmNo);
|
||||
}else{ // 查询默认
|
||||
lambdaQueryWrapper .eq(MchStoreTerminal::getDefaultFlag, CS.YES);
|
||||
}
|
||||
|
||||
mchStoreTerminal = mchStoreTerminalService.getOne(lambdaQueryWrapper,false);
|
||||
if(mchStoreTerminal == null || mchStoreTerminal.getChannelBindInfo() == null){
|
||||
return null;
|
||||
}
|
||||
|
||||
TerminalChannelModel model = mchStoreTerminal.getChannelBindInfo().getObject(payOrder.getIfCode(), TerminalChannelModel.class);
|
||||
|
||||
if(model != null && model.getState() != null && model.getState() == TerminalChannelModel.STATE_SUCCESS && StringUtils.isNotEmpty(model.getChannelTrmNo())){
|
||||
|
||||
return model.getChannelTrmNo();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.beans.RequestKitBean;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IPosNoticeService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
/*
|
||||
* 实现回调接口抽象类
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:18
|
||||
*/
|
||||
public abstract class AbstractPosNoticeService implements IPosNoticeService {
|
||||
|
||||
@Autowired private RequestKitBean requestKitBean;
|
||||
@Autowired private ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
|
||||
|
||||
/** 文本类型的响应数据 **/
|
||||
protected ResponseEntity textResp(String text){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.TEXT_HTML);
|
||||
return new ResponseEntity(text, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/** json类型的响应数据 **/
|
||||
protected ResponseEntity jsonResp(Object body){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
return new ResponseEntity(body, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected JSONObject getReqParamJSON() {
|
||||
return requestKitBean.getReqParamJSON();
|
||||
}
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected String getReqParamFromBody() {
|
||||
return requestKitBean.getReqParamFromBody();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.entity.RefundOrder;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IRefundService;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRefundLimit;
|
||||
import com.jeequan.jeepay.core.model.terminal.TerminalChannelModel;
|
||||
import com.jeequan.jeepay.db.entity.AccountInfo;
|
||||
import com.jeequan.jeepay.db.entity.MchStoreTerminal;
|
||||
import com.jeequan.jeepay.service.impl.AccountInfoService;
|
||||
import com.jeequan.jeepay.service.impl.MchStoreTerminalService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/*
|
||||
* 退款接口抽象类
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/17 9:37
|
||||
*/
|
||||
public abstract class AbstractRefundService implements IRefundService {
|
||||
|
||||
@Autowired protected SysConfigService sysConfigService;
|
||||
@Autowired protected ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
@Autowired private MchStoreTerminalService mchStoreTerminalService;
|
||||
@Autowired protected AccountInfoService accountInfoService;
|
||||
|
||||
@Override
|
||||
public String getIfCode(RefundOrder refundOrder) {
|
||||
return refundOrder.getIfCode();
|
||||
}
|
||||
|
||||
protected String getNotifyUrl(){
|
||||
return sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/refund/notify/" + getIfCode();
|
||||
}
|
||||
|
||||
protected String getNotifyUrl(String refundOrderId){
|
||||
return sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/refund/notify/" + getIfCode() + "/" + refundOrderId;
|
||||
}
|
||||
|
||||
protected String getPosNotifyUrl(){
|
||||
return sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/pos/pay/notify/" + getIfCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找出对应的设备信息
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2022/4/29 15:20
|
||||
*/
|
||||
protected String queryStoreTerminalChannelTrmNo(String trmNo, PayOrder payOrder){
|
||||
|
||||
MchStoreTerminal mchStoreTerminal = null;
|
||||
|
||||
LambdaQueryWrapper<MchStoreTerminal> lambdaQueryWrapper = MchStoreTerminal.gw()
|
||||
.eq(MchStoreTerminal::getMchNo, payOrder.getMchNo())
|
||||
.eq(MchStoreTerminal::getAppId, payOrder.getAppId())
|
||||
.eq(MchStoreTerminal::getStoreId, payOrder.getStoreId())
|
||||
.eq(MchStoreTerminal::getState, CS.YES);
|
||||
|
||||
// 指定编号查询
|
||||
if(StringUtils.isNotEmpty(trmNo)){
|
||||
|
||||
lambdaQueryWrapper.eq(MchStoreTerminal::getTrmNo, trmNo);
|
||||
}else{ // 查询默认
|
||||
lambdaQueryWrapper .eq(MchStoreTerminal::getDefaultFlag, CS.YES);
|
||||
}
|
||||
|
||||
mchStoreTerminal = mchStoreTerminalService.getOne(lambdaQueryWrapper,false);
|
||||
if(mchStoreTerminal == null || mchStoreTerminal.getChannelBindInfo() == null){
|
||||
return null;
|
||||
}
|
||||
|
||||
TerminalChannelModel model = mchStoreTerminal.getChannelBindInfo().getObject(getIfCode(), TerminalChannelModel.class);
|
||||
|
||||
if(model != null && model.getState() != null && model.getState() == TerminalChannelModel.STATE_SUCCESS && StringUtils.isNotEmpty(model.getChannelTrmNo())){
|
||||
|
||||
return model.getChannelTrmNo();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款权限判断
|
||||
* @param settleType
|
||||
* @param applyId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChannelRefundLimit isRefundLimit(String settleType,String applyId){
|
||||
ChannelRefundLimit refundLimit = new ChannelRefundLimit(false,true);
|
||||
return refundLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验平台账户余额
|
||||
* @param refundOrder
|
||||
*/
|
||||
@Override
|
||||
public void checkPlatAccount(RefundOrder refundOrder){
|
||||
if(RefundOrder.REFUND_ACCOUNT_PLAT.equals(refundOrder.getExtParam())){
|
||||
accountInfoService.checkBalance(refundOrder.getMchNo(), AccountInfo.Type.REFUND,refundOrder.getRefundAmount());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IRepayApiService;
|
||||
import com.jeequan.jeepay.core.model.df.Account;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @author crystal
|
||||
* @date 2024/3/25 10:43
|
||||
*/
|
||||
public abstract class AbstractRepayApiService implements IRepayApiService {
|
||||
|
||||
@Autowired
|
||||
protected SysConfigService sysConfigService;
|
||||
@Autowired protected ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
|
||||
protected String getPaySiteUrl() {
|
||||
return sysConfigService.getDBApplicationConfig().getPaySiteUrl();
|
||||
}
|
||||
|
||||
protected String getNotifyUrl(){
|
||||
return getPaySiteUrl() + "/api/channel/payment/notify/" + getIfCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验账户余额
|
||||
* @param mchNo
|
||||
* @param accountType
|
||||
* @param changeAmt
|
||||
*/
|
||||
@Override
|
||||
public void checkAccountBalance(String mchNo,byte accountType, Long changeAmt) {
|
||||
Account account = this.queryAccountBalance(mchNo, accountType);
|
||||
if(account.getBalance() < changeAmt){
|
||||
throw new BizException("账户不足,请先在后台充值后再操作");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.beans.RequestKitBean;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IRepayNoticeService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/*
|
||||
* 实现回调接口抽象类
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:18
|
||||
*/
|
||||
public abstract class AbstractRepayNoticeService implements IRepayNoticeService {
|
||||
|
||||
@Autowired private RequestKitBean requestKitBean;
|
||||
@Autowired private ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
|
||||
/** 文本类型的响应数据 **/
|
||||
protected ResponseEntity textResp(String text){
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.TEXT_HTML);
|
||||
return new ResponseEntity(text, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/** json类型的响应数据 **/
|
||||
protected ResponseEntity jsonResp(Object body){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
return new ResponseEntity(body, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected JSONObject getReqParamJSON() {
|
||||
return requestKitBean.getReqParamJSON();
|
||||
}
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected String getReqParamFromBody() {
|
||||
return requestKitBean.getReqParamFromBody();
|
||||
}
|
||||
|
||||
/** 获取文件路径 **/
|
||||
protected String getCertFilePath(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFilePath(certFilePath);
|
||||
}
|
||||
|
||||
/** 获取文件File对象 **/
|
||||
protected File getCertFile(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFile(certFilePath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.beans.RequestKitBean;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.ITransferNoticeService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
|
||||
/*
|
||||
* 实现回调接口抽象类
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2022/12/30 10:18
|
||||
*/
|
||||
public abstract class AbstractTransferNoticeService implements ITransferNoticeService {
|
||||
|
||||
@Autowired private RequestKitBean requestKitBean;
|
||||
@Autowired private ChannelCertConfigKitBean channelCertConfigKitBean;
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public ResponseEntity doNotifyOrderNotExists(HttpServletRequest request) {
|
||||
return textResp("order not exists");
|
||||
}
|
||||
|
||||
/** 文本类型的响应数据 **/
|
||||
protected ResponseEntity textResp(String text){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.TEXT_HTML);
|
||||
return new ResponseEntity(text, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/** json类型的响应数据 **/
|
||||
protected ResponseEntity jsonResp(Object body){
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
return new ResponseEntity(body, httpHeaders, HttpStatus.OK);
|
||||
}
|
||||
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected JSONObject getReqParamJSON() {
|
||||
return requestKitBean.getReqParamJSON();
|
||||
}
|
||||
|
||||
/**request.getParameter 获取参数 并转换为JSON格式 **/
|
||||
protected String getReqParamFromBody() {
|
||||
return requestKitBean.getReqParamFromBody();
|
||||
}
|
||||
|
||||
/** 获取文件路径 **/
|
||||
protected String getCertFilePath(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFilePath(certFilePath);
|
||||
}
|
||||
|
||||
/** 获取文件File对象 **/
|
||||
protected File getCertFile(String certFilePath) {
|
||||
return channelCertConfigKitBean.getCertFile(certFilePath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import cn.hutool.core.date.DateField;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.AccountOperate;
|
||||
import com.jeequan.jeepay.core.entity.TransferOrder;
|
||||
import com.jeequan.jeepay.core.entity.TransferWallet;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.ITransferService;
|
||||
import com.jeequan.jeepay.core.model.rqrs.transfer.TransferOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.tranfer.TransferBasicInfo;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.db.entity.AccountFundInfo;
|
||||
import com.jeequan.jeepay.db.entity.AccountInfo;
|
||||
import com.jeequan.jeepay.db.entity.TransferSubjectEntity;
|
||||
import com.jeequan.jeepay.db.entity.TransferWalletEntity;
|
||||
import com.jeequan.jeepay.service.impl.*;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 支付接口抽象类
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @since 2021/6/8 17:18
|
||||
*/
|
||||
public abstract class AbstractTransferService implements ITransferService {
|
||||
|
||||
@Autowired protected TransferOrderService transferOrderService;
|
||||
|
||||
@Autowired protected TransferWalletService transferWalletService;
|
||||
|
||||
@Autowired protected TransferSubjectService transferSubjectService;
|
||||
|
||||
@Autowired protected SysConfigService sysConfigService;
|
||||
|
||||
@Autowired protected AccountInfoService accountInfoService;
|
||||
|
||||
protected String getPaySiteUrl() {
|
||||
return sysConfigService.getDBApplicationConfig().getPaySiteUrl();
|
||||
}
|
||||
|
||||
protected String getNotifyUrl(){
|
||||
return getPaySiteUrl() + "/api/transfer/notify/" + getIfCode();
|
||||
}
|
||||
|
||||
protected String getNotifyUrl(String payOrderId){
|
||||
return getPaySiteUrl() + "/api/transfer/notify/" + getIfCode() + "/" + payOrderId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<String, Long> queryBalanceAmount(TransferWallet transferWallet) {;
|
||||
return MutablePair.of(null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String preCheck(TransferOrderRQ bizRQ, TransferOrder transferOrder) {
|
||||
commonCheck(bizRQ, transferOrder);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commonCheck(TransferOrderRQ bizRQ, TransferOrder transferOrder) {
|
||||
checkAmountLimit(bizRQ, transferOrder);
|
||||
checkRateAccountFee(bizRQ, transferOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 交易限额的校验
|
||||
*/
|
||||
protected final void checkAmountLimit(TransferOrderRQ bizRQ, TransferOrder transferOrder) {
|
||||
String transferSubjectIdFq = transferOrder.getTransferSubjectIdFq();
|
||||
TransferWalletEntity transferWallet = transferWalletService.getByApplyId(transferSubjectIdFq, null);
|
||||
|
||||
Long monthLimit;
|
||||
Long dayLimit;
|
||||
|
||||
String transferTypeName;
|
||||
switch (transferOrder.getEntryType()) {
|
||||
case TransferOrder.ENTRY_BANK_CARD:
|
||||
if (transferOrder.getAccountType().equals(TransferBasicInfo.ACCOUNT_TYPE_COR)) {
|
||||
transferTypeName = "对公账户";
|
||||
// 对公
|
||||
if (transferOrder.getAmount() > transferWallet.getBankCardCorOnceMax()) {
|
||||
throw new BizException("转账单笔超限额[" + AmountUtil.convertCent2Dollar(transferWallet.getBankCardCorOnceMax()) + "]");
|
||||
}
|
||||
} else {
|
||||
transferTypeName = "个人银行卡";
|
||||
// 对私
|
||||
if (transferOrder.getAmount() > transferWallet.getBankCardPriOnceMax()) {
|
||||
throw new BizException("转账个人银行卡单笔超限额[" + AmountUtil.convertCent2Dollar(transferWallet.getBankCardPriOnceMax()) + "]");
|
||||
}
|
||||
}
|
||||
|
||||
monthLimit = transferWallet.getBankCardMonthMax();
|
||||
dayLimit = transferWallet.getBankCardDayMax();
|
||||
break;
|
||||
case TransferOrder.ENTRY_WX_CASH:
|
||||
if (transferOrder.getAccountType().equals(TransferBasicInfo.ACCOUNT_TYPE_COR)) {
|
||||
transferTypeName = "企业微信";
|
||||
// 企业微信
|
||||
if (transferOrder.getAmount() > transferWallet.getWxCorOnceMax()) {
|
||||
throw new BizException("转账企业微信单笔超限额[" + AmountUtil.convertCent2Dollar(transferWallet.getWxCorOnceMax()) + "]");
|
||||
}
|
||||
} else {
|
||||
transferTypeName = "个人微信";
|
||||
// 对私
|
||||
if (transferOrder.getAmount() > transferWallet.getWxPriOnceMax()) {
|
||||
throw new BizException("转账个人微信单笔超限额[" + AmountUtil.convertCent2Dollar(transferWallet.getWxPriOnceMax()) + "]");
|
||||
}
|
||||
}
|
||||
|
||||
monthLimit = transferWallet.getWxMonthMax();
|
||||
dayLimit = transferWallet.getWxDayMax();
|
||||
break;
|
||||
case TransferOrder.ENTRY_ALIPAY_CASH:
|
||||
if (transferOrder.getAccountType().equals(TransferBasicInfo.ACCOUNT_TYPE_COR)) {
|
||||
transferTypeName = "企业支付宝";
|
||||
// 对公
|
||||
if (transferOrder.getAmount() > transferWallet.getZfbCorOnceMax()) {
|
||||
throw new BizException("转账企业支付宝单笔超限额[" + AmountUtil.convertCent2Dollar(transferWallet.getZfbCorOnceMax()) + "]");
|
||||
}
|
||||
} else {
|
||||
transferTypeName = "个人支付宝";
|
||||
// 对私
|
||||
if (transferOrder.getAmount() > transferWallet.getZfbPriOnceMax()) {
|
||||
throw new BizException("转账个人支付宝单笔超限额[" + AmountUtil.convertCent2Dollar(transferWallet.getZfbPriOnceMax()) + "]");
|
||||
}
|
||||
}
|
||||
|
||||
monthLimit = transferWallet.getZfbMonthMax();
|
||||
dayLimit = transferWallet.getZfbDayMax();
|
||||
break;
|
||||
default:
|
||||
throw new BizException("未知的打款方式");
|
||||
}
|
||||
|
||||
Date current = new Date();
|
||||
Long accumulatedMonth = transferOrderService.accumulated(DateField.MONTH, current,
|
||||
TransferOrder.TRANSFER_TYPE_OUT, transferOrder.getEntryType(), transferSubjectIdFq,
|
||||
TransferOrder.STATE_INIT, TransferOrder.STATE_ING, TransferOrder.STATE_SUCCESS);
|
||||
|
||||
if (accumulatedMonth + transferOrder.getAmount() > monthLimit) {;
|
||||
throw new BizException("操作失败,转账" + transferTypeName + "已达到月限额[" + monthLimit + "]");
|
||||
}
|
||||
|
||||
Long accumulatedDay = transferOrderService.accumulated(DateField.DAY_OF_YEAR, current,
|
||||
TransferOrder.TRANSFER_TYPE_OUT, transferOrder.getEntryType(), transferSubjectIdFq,
|
||||
TransferOrder.STATE_INIT, TransferOrder.STATE_ING, TransferOrder.STATE_SUCCESS);
|
||||
|
||||
if (accumulatedDay + transferOrder.getAmount() > dayLimit) {
|
||||
throw new BizException("操作失败,转账" + transferTypeName + "已达到日限额[" + dayLimit + "]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 手续费校验
|
||||
*/
|
||||
protected final void checkRateAccountFee(TransferOrderRQ bizRQ, TransferOrder transferOrder) {
|
||||
// 手续费外扣,需要校验余额
|
||||
if (transferOrder.getFeeCostType().equals(TransferOrder.COST_TYPE_ACCOUNT)) {
|
||||
// 校验余额,
|
||||
TransferSubjectEntity transferSubject = transferSubjectService.getById(transferOrder.getTransferSubjectIdFq());
|
||||
String infoId;
|
||||
if (transferSubject.getInfoType().equals(CS.SYS_ROLE_TYPE.MCH)) {
|
||||
infoId = transferSubject.getMchNo();
|
||||
} else {
|
||||
infoId = transferSubject.getAgentNo();
|
||||
}
|
||||
|
||||
AccountInfo accountInfo = accountInfoService.getAccountInfo(infoId, AccountInfo.Type.SERVICE_CHARGE.getType());
|
||||
if (accountInfo.getBalacne() < transferOrder.getMchOrderFeeAmount()) {
|
||||
throw new BizException("当前手续费余额不足");
|
||||
}
|
||||
|
||||
// 预扣手续费
|
||||
AccountOperate accountOperate = new AccountOperate(accountInfo.getAccountNo(), transferOrder.getAmount(),
|
||||
AccountFundInfo.ChangeType.TRANSFER.getValue(), AccountFundInfo.ChangeMethod.DF.getValue(),
|
||||
transferOrder.getTransferId(), "代付手续费");
|
||||
accountOperate.setFinalAmt(transferOrder.getMchOrderFeeAmount());
|
||||
accountOperate.setIsUpdateAccount(true);
|
||||
accountInfoService.upAccount(accountOperate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel;
|
||||
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.*;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 返回各个通道的的
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class IsvFactory {
|
||||
public static IIsvmchApplymentService getIsvMchApplymentService(String ifCode) {
|
||||
return SpringBeansUtil.getBean(ifCode + "MchApplymentService", IIsvmchApplymentService.class);
|
||||
}
|
||||
|
||||
public static IIsvmchWxConfigService getIsvMchWxConfigService(String ifCode) {
|
||||
return SpringBeansUtil.getBean(ifCode + "IsvmchWxConfigService", IIsvmchWxConfigService.class);
|
||||
}
|
||||
|
||||
public static IIsvmchAlipayConfigService getIsvMchAlipayConfigService(String ifCode) {
|
||||
return SpringBeansUtil.getBean(ifCode + "IsvmchAlipayConfigService", IIsvmchAlipayConfigService.class);
|
||||
}
|
||||
|
||||
public static IIsvmchModifyApplymentService getIsvMchModifyApplymentService(String ifCode) {
|
||||
return SpringBeansUtil.getBean(ifCode + "IsvmchModifyApplymentService", IIsvmchModifyApplymentService.class);
|
||||
}
|
||||
|
||||
public static IGetApplymentDataService getGetApplymentDataService(String ifCode) {
|
||||
return SpringBeansUtil.getBean(ifCode + "GetApplymentDataService", IGetApplymentDataService.class);
|
||||
}
|
||||
|
||||
public static IIsvmchWrapper getIsvMchWrapper(String ifCode) {
|
||||
return SpringBeansUtil.getBean(ifCode + "IsvmchWrapper", IIsvmchWrapper.class);
|
||||
}
|
||||
|
||||
public static ITransferService getTransferService(String ifCode) {
|
||||
return SpringBeansUtil.getBean(ifCode + "TransferService", ITransferService.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.aliaqf;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.TransferSubject;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.transfer.IChannelTransferSubjectService;
|
||||
import com.jeequan.jeepay.core.model.params.aliaqf.AliaqfIsvParams;
|
||||
import com.jeequan.jeepay.db.entity.TransferSubjectEntity;
|
||||
import com.jeequan.jeepay.service.impl.TransferSubjectService;
|
||||
import com.jeequan.jeepay.thirdparty.channel.aliaqf.model.AliAqfTransferBasicInfo;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AliAqfV2Service;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @author deng
|
||||
* @since 2024/5/8
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AliaqfChannelTransferSubjectService implements IChannelTransferSubjectService<AliAqfTransferBasicInfo> {
|
||||
|
||||
@Autowired
|
||||
private TransferSubjectService transferSubjectService;
|
||||
|
||||
@Autowired
|
||||
private AliAqfV2Service aliAqfV2Service;
|
||||
@Autowired
|
||||
private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public void addExporter(AliAqfTransferBasicInfo transferBasicInfo) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAcceptor(AliAqfTransferBasicInfo transferBasicInfo) {
|
||||
throw new BizException("当前通道【安全发】不支持该操作");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callbackProcess(JSONObject bizContent) {
|
||||
log.info("安全发的签约回调, 回调参数为{}", bizContent);
|
||||
TransferSubjectEntity subjectEntity = transferSubjectService.getByApplyId(bizContent.getString("external_agreement_no"));
|
||||
|
||||
AliaqfIsvParams isvParams = (AliaqfIsvParams) configContextQueryService.queryTransferIsvParams(subjectEntity.getIsvNo(), CS.IF_CODE.ALIAQF);
|
||||
try {
|
||||
//验签
|
||||
if (!AliaqfKit.checkSign(bizContent, isvParams)) {
|
||||
log.error("安全发签约回调验签失败");
|
||||
return;
|
||||
}
|
||||
|
||||
subjectEntity.setTransChannelSignNo(bizContent.getString("agreement_no"));
|
||||
subjectEntity.setSuccResParameter(bizContent.toJSONString());
|
||||
|
||||
switch (bizContent.getString("status")) {
|
||||
case "NORMAL":
|
||||
subjectEntity.setSignState((int) TransferSubject.SIGN_STATE_SUCCESS);
|
||||
transferSubjectService.updateById(subjectEntity);
|
||||
// 开通记账本
|
||||
aliAqfV2Service.fundAccountbookCreate(subjectEntity.getId());
|
||||
break;
|
||||
case "TEMP":
|
||||
subjectEntity.setSignState((int) TransferSubject.SIGN_STATE_ON_HOLD);
|
||||
transferSubjectService.updateById(subjectEntity);
|
||||
break;
|
||||
case "STOP":
|
||||
subjectEntity.setSignState((int) TransferSubject.SIGN_STATE_ON_PAUSE);
|
||||
transferSubjectService.updateById(subjectEntity);
|
||||
break;
|
||||
default:
|
||||
subjectEntity.setSignState((int) TransferSubject.SIGN_STATE_UNKNOWN);
|
||||
transferSubjectService.updateById(subjectEntity);
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("安全发签约回调异常", e);
|
||||
transferSubjectService.updateById(subjectEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object retOk(JSONObject bizContent) {
|
||||
return "SUCCESS";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.aliaqf;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.alipay.api.internal.util.AlipaySignature;
|
||||
import com.jeequan.jeepay.core.model.params.aliaqf.AliaqfIsvParams;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayConfig;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 安全发的一些通用请求,签名等
|
||||
*
|
||||
* @author deng
|
||||
* @since 2024/5/9
|
||||
*/
|
||||
@Slf4j
|
||||
public class AliaqfKit {
|
||||
|
||||
// alipay.fund.trans.uni.transfer 涉及的状态:SUCCESS、FAIL、DEALING、REFUND
|
||||
public static final String ORDER_SUCCESS = "SUCCESS";
|
||||
/** 处理中 */
|
||||
public static final String ORDER_DEALING = "DEALING";
|
||||
/** 退票 */
|
||||
public static final String ORDER_REFUND = "REFUND";
|
||||
/** 失败 */
|
||||
public static final String ORDER_FAIL = "FAIL";
|
||||
|
||||
public static boolean checkSign(JSONObject reqParamJSON, AliaqfIsvParams isvParams) {
|
||||
try {
|
||||
TypeReference<Map<String, String>> mapTypeReference = new TypeReference<Map<String, String>>() {
|
||||
};
|
||||
ChannelCertConfigKitBean channelCertConfigKitBean = SpringBeansUtil.getBean(ChannelCertConfigKitBean.class);
|
||||
return AlipaySignature.rsaCertCheckV1(reqParamJSON.toJavaObject(mapTypeReference), channelCertConfigKitBean.getCertFilePath(isvParams.getAlipayPublicCert()),
|
||||
AlipayConfig.CHARSET, "RSA2");
|
||||
} catch (Exception e) {
|
||||
log.info("验签失败", e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.aliaqf;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alipay.api.AlipayClient;
|
||||
import com.alipay.api.CertAlipayRequest;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.domain.AlipayFundTransCommonQueryModel;
|
||||
import com.alipay.api.domain.AlipayFundTransUniTransferModel;
|
||||
import com.alipay.api.domain.BankcardExtInfo;
|
||||
import com.alipay.api.domain.Participant;
|
||||
import com.alipay.api.request.AlipayFundTransCommonQueryRequest;
|
||||
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
|
||||
import com.alipay.api.response.AlipayFundAccountbookQueryResponse;
|
||||
import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
|
||||
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.AccountOperate;
|
||||
import com.jeequan.jeepay.core.entity.TransferOrder;
|
||||
import com.jeequan.jeepay.core.entity.TransferWallet;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.aliaqf.AliaqfIsvParams;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayConfig;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.transfer.TransferOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.tranfer.TransferBasicInfo;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.db.entity.*;
|
||||
import com.jeequan.jeepay.service.impl.AccountInfoService;
|
||||
import com.jeequan.jeepay.service.impl.TransferInterfaceConfigService;
|
||||
import com.jeequan.jeepay.service.impl.TransferSubjectService;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractTransferService;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AliAqfV2Service;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @author deng
|
||||
* @since 2024/5/11
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AliaqfTransferService extends AbstractTransferService {
|
||||
private final AccountInfoService accountInfoService;
|
||||
private final TransferSubjectService transferSubjectService;
|
||||
private final TransferInterfaceConfigService interfaceConfigService;
|
||||
private final AliAqfV2Service aliAqfV2Service;
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.ALIAQF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupport(String entryType) {
|
||||
return TransferBasicInfo.ENTRY_TYPE_BANK.equals(entryType) || TransferBasicInfo.ENTRY_TYPE_ZFB.equals(entryType);
|
||||
}
|
||||
|
||||
public void rollBackServiceCharge(TransferOrder transferOrder) {
|
||||
// 预扣手续费回退
|
||||
TransferSubjectEntity transferSubject = transferSubjectService.getById(transferOrder.getTransferSubjectIdFq());
|
||||
String infoId;
|
||||
if (transferSubject.getInfoType().equals(CS.SYS_ROLE_TYPE.MCH)) {
|
||||
infoId = transferSubject.getMchNo();
|
||||
} else {
|
||||
infoId = transferSubject.getAgentNo();
|
||||
}
|
||||
AccountInfo accountInfo = accountInfoService.getAccountInfo(infoId, AccountInfo.Type.SERVICE_CHARGE.getType());
|
||||
|
||||
// 预扣手续费
|
||||
AccountOperate accountOperate = new AccountOperate(accountInfo.getAccountNo(), transferOrder.getAmount(),
|
||||
AccountFundInfo.ChangeType.TRANSFER.getValue(), AccountFundInfo.ChangeMethod.DF.getValue(),
|
||||
transferOrder.getTransferId(), "代付失败手续费回退");
|
||||
accountOperate.setFinalAmt(-transferOrder.getMchOrderFeeAmount());
|
||||
accountOperate.setIsUpdateAccount(true);
|
||||
accountInfoService.upAccount(accountOperate);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg transfer(TransferOrderRQ bizRQ, TransferOrder transferOrder) throws Exception {
|
||||
log.info("进入了支付宝直付通代发!");
|
||||
ChannelRetMsg retMsg = ChannelRetMsg.waiting();
|
||||
|
||||
CertAlipayRequest certAlipayRequest = getCertAliPayRequest(transferOrder.getIsvNo());
|
||||
TransferSubjectEntity ersubjectEntity = transferSubjectService.getById(transferOrder.getTransferSubjectIdFq());
|
||||
TransferSubjectEntity eesubjectEntity = transferSubjectService.getById(transferOrder.getTransferSubjectIdJs());
|
||||
try {
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
|
||||
AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
|
||||
AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
|
||||
|
||||
model.setOutBizNo(transferOrder.getTransferId());
|
||||
model.setTransAmount(AmountUtil.convertCent2Dollar(transferOrder.getAmount()));
|
||||
model.setProductCode("SINGLE_TRANSFER_NO_PWD");
|
||||
model.setBizScene("ENTRUST_TRANSFER");
|
||||
model.setOrderTitle(StringUtils.isNotEmpty(transferOrder.getTransferDesc()) ? transferOrder.getTransferDesc() : "支付宝代发到户!");
|
||||
//付款方信息
|
||||
Participant participanter = new Participant();
|
||||
participanter.setIdentity(ersubjectEntity.getTransChannelMchNo());
|
||||
participanter.setIdentityType("ACCOUNT_BOOK_ID");
|
||||
JSONObject erparm = new JSONObject();
|
||||
erparm.put("agreement_no", ersubjectEntity.getTransChannelSignNo());
|
||||
participanter.setExtInfo(erparm.toJSONString());
|
||||
model.setPayerInfo(participanter);
|
||||
//收款方信息
|
||||
Participant participantee = new Participant();
|
||||
participantee.setIdentity(eesubjectEntity.getAccount());
|
||||
if (TransferOrderEntity.ENTRY_ALIPAY_CASH.equals(transferOrder.getEntryType())){
|
||||
participantee.setIdentityType("ALIPAY_LOGON_ID");
|
||||
participantee.setName(eesubjectEntity.getAccountName());
|
||||
}else if (TransferOrderEntity.ENTRY_BANK_CARD.equals(transferOrder.getEntryType())){
|
||||
participantee.setIdentityType("BANKCARD_ACCOUNT");
|
||||
BankcardExtInfo bankcardExtInfo = new BankcardExtInfo();
|
||||
participantee.setName(eesubjectEntity.getAccountName());
|
||||
if (eesubjectEntity.getAccountType() == TransferBasicInfo.ACCOUNT_TYPE_COR) {
|
||||
//对公
|
||||
String accountMessage = eesubjectEntity.getAccountMessage();
|
||||
if (StringUtils.isNotEmpty(accountMessage)) {
|
||||
JSONObject jsonObject = JSONObject.parseObject(accountMessage);
|
||||
bankcardExtInfo.setAccountType("1");
|
||||
bankcardExtInfo.setInstName(jsonObject.getString("instName"));
|
||||
bankcardExtInfo.setInstProvince(jsonObject.getString("instProvince"));
|
||||
bankcardExtInfo.setInstCity(jsonObject.getString("instCity"));
|
||||
bankcardExtInfo.setInstBranchName(jsonObject.getString("instBranchName"));
|
||||
participantee.setBankcardExtInfo(bankcardExtInfo);
|
||||
transferOrder.setBankName(jsonObject.getString("instName"));
|
||||
}
|
||||
} else {
|
||||
//对私
|
||||
bankcardExtInfo.setAccountType("2");
|
||||
participantee.setBankcardExtInfo(bankcardExtInfo);
|
||||
}
|
||||
}
|
||||
model.setPayeeInfo(participantee);
|
||||
request.setBizModel(model);
|
||||
AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request);
|
||||
retMsg.setChannelAttach(response.getBody());
|
||||
if (response.isSuccess()) {
|
||||
retMsg.setChannelOrderId(response.getOrderId());
|
||||
retMsg.setPlatformOrderNo(response.getPayFundOrderId());
|
||||
} else {
|
||||
retMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
retMsg.setChannelErrMsg(response.getSubMsg());
|
||||
retMsg.setChannelErrCode(response.getSubCode());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.info("代发异常!",e);
|
||||
retMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
retMsg.setChannelErrMsg(e.getMessage());
|
||||
|
||||
rollBackServiceCharge(transferOrder);
|
||||
}
|
||||
return retMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg query(TransferOrder transferOrder, MchAppConfigContext mchAppConfigContext) {
|
||||
log.info("进入了支付宝账单查询");
|
||||
|
||||
TransferSubjectEntity transferSubjectFq = transferSubjectService.getById(transferOrder.getTransferSubjectIdFq());
|
||||
CertAlipayRequest certAlipayRequest = getCertAliPayRequest(transferSubjectFq.getIsvNo());
|
||||
AlipayFundTransCommonQueryResponse response;
|
||||
if ( transferSubjectFq.getTransChannelSignNo() == null || transferSubjectFq.getTransChannelMchNo() == null) {
|
||||
throw new BizException("当前付款人签约或开通记账本!");
|
||||
}
|
||||
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.UNKNOWN);
|
||||
try {
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
|
||||
AlipayFundTransCommonQueryRequest request = new AlipayFundTransCommonQueryRequest();
|
||||
AlipayFundTransCommonQueryModel model = new AlipayFundTransCommonQueryModel();
|
||||
model.setProductCode(TransferOrder.ENTRY_BANK_CARD.equals(transferOrder.getEntryType()) ? "TRANS_BANKCARD_NO_PWD" : "TRANS_ACCOUNT_NO_PWD");
|
||||
model.setBizScene("DIRECT_TRANSFER");
|
||||
model.setOutBizNo(transferOrder.getTransferId());
|
||||
request.setBizModel(model);
|
||||
|
||||
channelRetMsg.setChannelOrderId(transferOrder.getChannelOrderNo());
|
||||
response = alipayClient.certificateExecute(request);
|
||||
channelRetMsg.setChannelOriginResponse(response.getBody());
|
||||
channelRetMsg.setResponseEntity(ResponseEntity.ok("SUCCESS"));
|
||||
|
||||
if (response.isSuccess()) {
|
||||
log.info("安全发账单查询成功:" + response.getBody());
|
||||
} else {
|
||||
log.error("安全发账单查询失败!" + response.getSubMsg());
|
||||
return channelRetMsg;
|
||||
}
|
||||
|
||||
String status = response.getStatus();
|
||||
if (AliaqfKit.ORDER_SUCCESS.equals(status)) {
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
channelRetMsg.setChannelOrderId(response.getOrderId());
|
||||
channelRetMsg.setPlatformOrderNo(response.getPayFundOrderId());
|
||||
} else if (AliaqfKit.ORDER_FAIL.equals(status)) {
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
rollBackServiceCharge(transferOrder);
|
||||
} else if (AliaqfKit.ORDER_DEALING.equals(status)) {
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
}
|
||||
|
||||
return channelRetMsg;
|
||||
} catch (Exception e) {
|
||||
log.info("支付宝安全发查询订单状态异常, {}", transferOrder.getTransferId(), e);
|
||||
}
|
||||
|
||||
return channelRetMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<String, Long> queryBalanceAmount(TransferWallet transferWallet) {
|
||||
AlipayFundAccountbookQueryResponse queryResultData = aliAqfV2Service.fundAccountbookQuery(transferWallet.getTransApplyId(), transferWallet.getWalletApplyId());
|
||||
|
||||
String availableAmount = queryResultData.getAvailableAmount();
|
||||
|
||||
return new MutablePair<>(transferWallet.getTransApplyId(), AmountUtil.convertDollar2CentLong(availableAmount));
|
||||
|
||||
}
|
||||
|
||||
public CertAlipayRequest getCertAliPayRequest(String isvNo) {
|
||||
TransferInterfaceConfigEntity transferInterfaceConfigEntity = interfaceConfigService.getTransferConfig(CS.IF_CODE.ALIAQF, isvNo, CS.SYS_ROLE_TYPE.ISV);
|
||||
Assert.notNull(transferInterfaceConfigEntity, "所选渠道配置不存在");
|
||||
|
||||
CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
|
||||
ChannelCertConfigKitBean channelCertConfigKitBean = SpringBeansUtil.getBean(ChannelCertConfigKitBean.class);
|
||||
AliaqfIsvParams isvParams = JSONObject.parseObject(transferInterfaceConfigEntity.getTransIfParams(), AliaqfIsvParams.class);
|
||||
// 支付宝网关
|
||||
certAlipayRequest.setServerUrl(AlipayConfig.PROD_SERVER_URL);
|
||||
certAlipayRequest.setAppId(isvParams.getAppId());
|
||||
certAlipayRequest.setPrivateKey(isvParams.getPrivateKey());
|
||||
certAlipayRequest.setCertPath(channelCertConfigKitBean.getCertFilePath(isvParams.getAppPublicCert()));
|
||||
certAlipayRequest.setAlipayPublicCertPath(channelCertConfigKitBean.getCertFilePath(isvParams.getAlipayPublicCert()));
|
||||
certAlipayRequest.setRootCertPath(channelCertConfigKitBean.getCertFilePath(isvParams.getAlipayRootCert()));
|
||||
certAlipayRequest.setSignType("RSA2");
|
||||
certAlipayRequest.setFormat("json");
|
||||
certAlipayRequest.setCharset("UTF-8");
|
||||
|
||||
return certAlipayRequest;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.aliaqf.model;
|
||||
|
||||
import com.jeequan.jeepay.core.model.tranfer.TransferBasicInfo;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @author deng
|
||||
* @since 2024/5/8
|
||||
*/
|
||||
public class AliAqfTransferBasicInfo extends TransferBasicInfo {
|
||||
}
|
||||
@@ -0,0 +1,778 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayClient;
|
||||
import com.alipay.api.CertAlipayRequest;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.diagnosis.DiagnosisUtils;
|
||||
import com.alipay.api.domain.*;
|
||||
import com.alipay.api.request.*;
|
||||
import com.alipay.api.response.*;
|
||||
import com.jeequan.jeepay.converter.TransferConverter;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.TransferOrder;
|
||||
import com.jeequan.jeepay.core.entity.TransferSubject;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.aliaqfbiz.IAliAqfV2ApiService;
|
||||
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
|
||||
import com.jeequan.jeepay.core.model.params.aliaqf.AliaqfIsvParams;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayConfig;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.tranfer.TransferBasicInfo;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.core.utils.SeqKit;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.db.entity.*;
|
||||
import com.jeequan.jeepay.service.impl.*;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AliAqfV2Service implements IAliAqfV2ApiService {
|
||||
|
||||
@Autowired
|
||||
private SysConfigService sysConfigService;
|
||||
|
||||
@Autowired
|
||||
private TransferInterfaceConfigService transferInterfaceConfigService;
|
||||
|
||||
@Autowired
|
||||
private TransferSubjectService transferSubjectService;
|
||||
|
||||
@Autowired
|
||||
private TransferOrderService transferOrderService;
|
||||
|
||||
@Autowired
|
||||
private TransferWalletService transferWalletService;
|
||||
|
||||
@Autowired
|
||||
private TaskListService taskListService;
|
||||
@Autowired
|
||||
private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Autowired
|
||||
private RateConfigService rateConfigService;
|
||||
|
||||
@Autowired
|
||||
private TransferConverter transferConverter;
|
||||
|
||||
@Autowired
|
||||
private AccountInfoService accountInfoService;
|
||||
|
||||
private String getOpenCallbackUrl(String subjectId) {
|
||||
return sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/transferSubject/notify/aliaqf/" + subjectId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 签约
|
||||
*/
|
||||
@Override
|
||||
public String userAgreementPageSign(String subId) {
|
||||
log.info("进入了支付宝签约");
|
||||
TransferSubjectEntity subjectEntity = getSubjectOne(subId);
|
||||
CertAlipayRequest certAlipayRequest = getCertAliPayRequest(subjectEntity.getIsvNo());
|
||||
if (subjectEntity.getState() == TransferSubject.STATE_DISABLE) {
|
||||
throw new BizException("当前付款账户已被停用!");
|
||||
}
|
||||
|
||||
Assert.notNull(subjectEntity.getTransApplyId(), "申请单号不能为空");
|
||||
|
||||
try {
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
|
||||
AlipayUserAgreementPageSignRequest request = new AlipayUserAgreementPageSignRequest();
|
||||
AlipayUserAgreementPageSignModel model = new AlipayUserAgreementPageSignModel();
|
||||
model.setPersonalProductCode("FUND_SAFT_SIGN_WITHHOLDING_P");
|
||||
AccessParams accessParams = new AccessParams();
|
||||
accessParams.setChannel("QRCODE");
|
||||
model.setAccessParams(accessParams);
|
||||
model.setProductCode("FUND_SAFT_SIGN_WITHHOLDING");
|
||||
model.setSignScene("INDUSTRY|SATF_ACC");
|
||||
//唯一标识,新建收款账户时生成,
|
||||
model.setExternalAgreementNo(subjectEntity.getTransApplyId());
|
||||
model.setThirdPartyType("PARTNER");
|
||||
request.setBizModel(model);
|
||||
|
||||
String openCallbackUrl = getOpenCallbackUrl(subjectEntity.getTransApplyId());
|
||||
request.setNotifyUrl(openCallbackUrl);
|
||||
log.info("安全发签约回调地址:" + openCallbackUrl);
|
||||
log.info("请求报文:{}", JSONObject.toJSONString(request));
|
||||
AlipayUserAgreementPageSignResponse response = alipayClient.pageExecute(request, "get");
|
||||
|
||||
String pageRedirectionData = response.getBody();
|
||||
|
||||
if (response.isSuccess()) {
|
||||
log.info("安全发签约返回:" + response.getBody());
|
||||
//设置为签约中
|
||||
subjectEntity.setSignState((int) TransferSubject.SIGN_STATE_AUDITING);
|
||||
subjectEntity.setChannelVar1(pageRedirectionData);
|
||||
transferSubjectService.updateById(subjectEntity);
|
||||
|
||||
return pageRedirectionData;
|
||||
} else {
|
||||
log.info("安全发签约发起请求失败");
|
||||
String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
|
||||
|
||||
if (ObjUtil.isEmpty(diagnosisUrl)) {
|
||||
throw new BizException(response.getSubMsg());
|
||||
}
|
||||
|
||||
return diagnosisUrl;
|
||||
}
|
||||
|
||||
} catch (AlipayApiException e) {
|
||||
log.error("安全发签约请求异常!");
|
||||
throw new BizException(e.getErrMsg());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝个人代扣协议查询接口
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public JSONObject userAgreementQuery(String subId) {
|
||||
log.info("进入了支付宝个人代扣协议查询接口");
|
||||
TransferSubjectEntity subjectEntity = getSubjectOne(subId);
|
||||
CertAlipayRequest certAlipayRequest = getCertAliPayRequest(subjectEntity.getIsvNo());
|
||||
JSONObject resut = new JSONObject();
|
||||
if (certAlipayRequest == null || subjectEntity.getTransApplyId() == null) {
|
||||
throw new BizException("未获取到当前用户相关信息!");
|
||||
}
|
||||
try {
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
|
||||
AlipayUserAgreementQueryRequest request = new AlipayUserAgreementQueryRequest();
|
||||
|
||||
AlipayUserAgreementQueryModel model = new AlipayUserAgreementQueryModel();
|
||||
model.setPersonalProductCode("FUND_SAFT_SIGN_WITHHOLDING_P");
|
||||
model.setSignScene("INDUSTRY|SATF_ACC");
|
||||
//签约时传入值
|
||||
model.setExternalAgreementNo(subjectEntity.getTransApplyId());
|
||||
model.setThirdPartyType("PARTNER");
|
||||
request.setBizModel(model);
|
||||
AlipayUserAgreementQueryResponse response = alipayClient.certificateExecute(request);
|
||||
resut = JSONObject.parseObject(response.getBody()).getJSONObject("alipay_user_agreement_query_response");
|
||||
} catch (Exception e) {
|
||||
log.error("支付宝个人代扣协议查询异常!",e);
|
||||
throw new BizException("支付宝个人代扣协议查询异常!");
|
||||
}
|
||||
return resut;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解约
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public JSONObject userAgreementUnsign(String subId) {
|
||||
log.info("进入了支付宝个人代扣协议解约接口");
|
||||
TransferSubjectEntity subjectEntity = getSubjectOne(subId);
|
||||
CertAlipayRequest certAlipayRequest = getCertAliPayRequest(subjectEntity.getIsvNo());
|
||||
JSONObject resut = new JSONObject();
|
||||
if (certAlipayRequest == null || subjectEntity.getTransApplyId() == null) {
|
||||
throw new BizException("未获取到当前用户相关信息!");
|
||||
}
|
||||
try {
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
|
||||
AlipayUserAgreementUnsignRequest request = new AlipayUserAgreementUnsignRequest();
|
||||
|
||||
AlipayUserAgreementUnsignModel model = new AlipayUserAgreementUnsignModel();
|
||||
model.setPersonalProductCode("FUND_SAFT_SIGN_WITHHOLDING_P");
|
||||
model.setSignScene("INDUSTRY|SATF_ACC");
|
||||
//签约时传入值
|
||||
model.setExternalAgreementNo(subjectEntity.getTransApplyId());
|
||||
//注意:仅异步解约需传入,其余情况无需传递本参数。
|
||||
// 解约确认: confirm
|
||||
//解约作废: invalid
|
||||
model.setOperateType("confirm");
|
||||
request.setBizModel(model);
|
||||
//request.setNotifyUrl(sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/anf/reqUnsign");
|
||||
//log.info("安全发解约回调地址:" + sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/anf/reqNotify");
|
||||
AlipayUserAgreementUnsignResponse response = alipayClient.certificateExecute(request);
|
||||
log.info("支付宝个人代扣协议解约返回参数:" + response.getBody());
|
||||
if (response.isSuccess()) {
|
||||
//直接就是已解约,异步返回暂时不处理
|
||||
subjectEntity.setSignState((int)TransferSubject.STATE_ENABLE_REVIEW);
|
||||
transferSubjectService.updateById(subjectEntity);
|
||||
} else {
|
||||
log.info("支付宝个人代扣协议解约失败:" + response.getSubMsg());
|
||||
}
|
||||
resut = JSONObject.parseObject(response.getBody()).getJSONObject("alipay_user_agreement_unsign_response");
|
||||
subjectEntity.setChannelVar1(response.getBody());
|
||||
} catch (Exception e) {
|
||||
log.error("支付宝个人代扣协议解约异常!",e);
|
||||
throw new BizException("支付宝个人代扣协议解约异常!");
|
||||
}
|
||||
return resut;
|
||||
}
|
||||
|
||||
/**
|
||||
* 资金记账本开通
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public void fundAccountbookCreate(String subId) {
|
||||
|
||||
log.info("进入资金记账本开通方法!");
|
||||
TransferSubjectEntity subjectEntity = getSubjectOne(subId);
|
||||
AliaqfIsvParams isvParams = ((AliaqfIsvParams) configContextQueryService.queryTransferIsvParams(subjectEntity.getIsvNo(), CS.IF_CODE.ALIAQF));
|
||||
|
||||
CertAlipayRequest certAlipayRequest = getCertAliPayRequest(subjectEntity.getIsvNo());
|
||||
JSONObject result = new JSONObject();
|
||||
TransferSubjectEntity transferSubject = transferSubjectService.getById(subId);
|
||||
|
||||
TransferWalletEntity transferWalletEntity = new TransferWalletEntity();
|
||||
AlipayFundAccountbookCreateResponse response;
|
||||
String merchantUserId = UUID.randomUUID().toString().replace("-", "");
|
||||
try {
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
|
||||
AlipayFundAccountbookCreateRequest request = new AlipayFundAccountbookCreateRequest();
|
||||
AlipayFundAccountbookCreateModel model = new AlipayFundAccountbookCreateModel();
|
||||
//外部商户系统会员的唯一标识,自定义传入
|
||||
model.setMerchantUserId(merchantUserId);
|
||||
model.setMerchantUserType("BUSINESS_ORGANIZATION");
|
||||
model.setSceneCode("SATF_FUND_BOOK");
|
||||
//扩展信息: 支付宝协议号必传、企业营业执照认证号(cert_no)可不传。
|
||||
//注意:ext_info字段本质上是String类型,所以传递的是转义后的json字符串。
|
||||
//agreement_no 签约时回调返回的参数值
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("agreement_no", transferSubject.getTransChannelSignNo());
|
||||
model.setExtInfo(param.toJSONString());
|
||||
request.setBizModel(model);
|
||||
response = alipayClient.certificateExecute(request);
|
||||
//处理记账本返回信息
|
||||
log.info("支付宝安全发记账本开通请求返回参数, {}", response.getBody());
|
||||
String responseBody = response.getBody();
|
||||
if (response.isSuccess()) {
|
||||
JSONObject jsonObject = JSONObject.parseObject(responseBody);
|
||||
ExtCardInfo extCardInfo = response.getExtCardInfo();
|
||||
transferSubject.setTransChannelMchNo(response.getAccountBookId());
|
||||
//记账本信息
|
||||
transferWalletEntity.setTransApplyId(transferSubject.getTransApplyId());
|
||||
transferWalletEntity.setTransChannelMchNo(response.getAccountBookId());
|
||||
transferWalletEntity.setTransIfCode(transferSubject.getTransIfCode());
|
||||
transferWalletEntity.setWalletApplyId(model.getMerchantUserId());
|
||||
transferWalletEntity.setExtResponse(jsonObject.toJSONString());
|
||||
transferWalletEntity.setIsvNo(transferSubject.getIsvNo());
|
||||
transferWalletEntity.setMchNo(transferSubject.getMchNo());
|
||||
transferWalletEntity.setSubjectName(transferSubject.getSubjectName());
|
||||
transferWalletEntity.setTransIfCode(CS.IF_CODE.ALIAQF);
|
||||
|
||||
transferWalletEntity.setWxMonthMax(0L);
|
||||
transferWalletEntity.setWxDayMax(0L);
|
||||
transferWalletEntity.setWxPriOnceMax(0L);
|
||||
transferWalletEntity.setWxCorOnceMax(0L);
|
||||
transferWalletEntity.setBankCardCorOnceMax(Long.parseLong(isvParams.getSubBankCardCorOnceMax()));
|
||||
transferWalletEntity.setBankCardPriOnceMax(Long.parseLong(isvParams.getSubBankCardPriOnceMax()));
|
||||
transferWalletEntity.setBankCardMonthMax(Long.parseLong(isvParams.getSubBankCardMonthMax()));
|
||||
transferWalletEntity.setBankCardDayMax(Long.parseLong(isvParams.getSubBankCardDayMax()));
|
||||
transferWalletEntity.setZfbCorOnceMax(Long.parseLong(isvParams.getSubZfbCorOnceMax()));
|
||||
transferWalletEntity.setZfbPriOnceMax(Long.parseLong(isvParams.getSubZfbPriOnceMax()));
|
||||
transferWalletEntity.setZfbMonthMax(Long.parseLong(isvParams.getSubZfbMonthMax()));
|
||||
transferWalletEntity.setZfbDayMax(Long.parseLong(isvParams.getSubZfbDayMax()));
|
||||
|
||||
if (extCardInfo != null) {
|
||||
transferWalletEntity.setExtCardInfo(JSONObject.toJSONString(response.getExtCardInfo()));
|
||||
if ("A".equals(extCardInfo.getStatus())) {
|
||||
transferWalletEntity.setCardStatus(TransferWalletEntity.CARD_STATUS_NORMAL);
|
||||
} else {
|
||||
transferWalletEntity.setCardStatus(TransferWalletEntity.CARD_STATUS_OTHER);
|
||||
}
|
||||
}
|
||||
transferWalletService.save(transferWalletEntity);
|
||||
} else {
|
||||
log.info("资金记账本开通失败, {}", response.getSubMsg());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.info("资金记账本开通异常", e);
|
||||
}
|
||||
transferSubjectService.updateById(transferSubject);
|
||||
}
|
||||
|
||||
/**
|
||||
* 资金记账本的信息查询
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public AlipayFundAccountbookQueryResponse fundAccountbookQuery(String subId, String walletApplyId) {
|
||||
log.info("进入了支付宝资金记账本的信息查询");
|
||||
TransferSubjectEntity subjectEntity = getSubjectOne(subId);
|
||||
CertAlipayRequest certAlipayRequest = getCertAliPayRequest(subjectEntity.getIsvNo());
|
||||
AlipayFundAccountbookQueryResponse response;
|
||||
if (certAlipayRequest == null || subjectEntity.getTransChannelSignNo() == null
|
||||
|| subjectEntity.getTransChannelMchNo() == null) {
|
||||
throw new BizException("当前用户暂未签约或配置!");
|
||||
}
|
||||
|
||||
try {
|
||||
TransferWalletEntity walletServiceOne = transferWalletService.getByApplyId(subjectEntity.getTransApplyId(), walletApplyId);
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
|
||||
AlipayFundAccountbookQueryRequest request = new AlipayFundAccountbookQueryRequest();
|
||||
AlipayFundAccountbookQueryModel model = new AlipayFundAccountbookQueryModel();
|
||||
//资金记账本id,开通时的返回值
|
||||
model.setAccountBookId(subjectEntity.getTransChannelMchNo());
|
||||
//商户会员的唯一标识 开通时自定义传入值
|
||||
model.setMerchantUserId(walletServiceOne.getWalletApplyId());
|
||||
model.setSceneCode("SATF_FUND_BOOK");
|
||||
//扩展信息: 支付宝协议号必传
|
||||
//注意:ext_info字段本质上是String类型,所以传递的是转义后的json字符串。
|
||||
//agreement_no 签约时回调返回的参数值
|
||||
JSONObject parm = new JSONObject();
|
||||
parm.put("agreement_no", subjectEntity.getTransChannelSignNo());
|
||||
model.setExtInfo(parm.toJSONString());
|
||||
request.setBizModel(model);
|
||||
|
||||
response = alipayClient.certificateExecute(request);
|
||||
if (response.isSuccess()) {
|
||||
String responseBody = response.getBody();
|
||||
JSONObject jsonObject = JSONObject.parseObject(responseBody);
|
||||
JSONObject accountbook = jsonObject.getJSONObject("alipay_fund_accountbook_query_response");
|
||||
walletServiceOne.setAccountBookBalance(AmountUtil.convertDollar2CentLong(accountbook.getString("available_amount")));
|
||||
JSONObject extCardInfo = accountbook.getJSONObject("ext_card_info");
|
||||
if (extCardInfo != null) {
|
||||
walletServiceOne.setExtCardInfo(extCardInfo.toJSONString());
|
||||
if ("A".equals(extCardInfo.getString("status"))) {
|
||||
walletServiceOne.setCardStatus(1);
|
||||
} else {
|
||||
walletServiceOne.setCardStatus(2);
|
||||
}
|
||||
}
|
||||
transferWalletService.updateById(walletServiceOne);
|
||||
} else {
|
||||
log.error("资金记账本的信息查询失败!" + response.getSubMsg());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("资金记账本的信息查询异常!",e);
|
||||
throw new BizException("资金记账本的信息查询异常!");
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 资金专款拨入(商户自身给记账本充值)
|
||||
*/
|
||||
@Override
|
||||
public String transPage(String subId, String transAmount ,String transferDesc) {
|
||||
log.info("进入了支付宝资金专款拨入(商户自身给记账本充值)");
|
||||
TransferSubjectEntity subjectEntity = getSubjectOne(subId);
|
||||
String resultUrl = null;
|
||||
CertAlipayRequest certAlipayRequest = getCertAliPayRequest(subjectEntity.getIsvNo());
|
||||
Assert.notNull(subjectEntity, "付款账户不存在");
|
||||
|
||||
//transferOrderService
|
||||
TransferOrderEntity transferOrder = new TransferOrderEntity();
|
||||
if (subjectEntity.getState() == TransferSubject.STATE_DISABLE) {
|
||||
throw new BizException("当前付款账户已被停用");
|
||||
}
|
||||
|
||||
//获取当前时间1小时后的时间作为过期时间
|
||||
String formattedDateTime = LocalDateTime.now().plusHours(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
|
||||
if (subjectEntity.getTransChannelMchNo() != null
|
||||
&& subjectEntity.getTransChannelSignNo() != null) {
|
||||
try {
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
|
||||
AlipayFundTransPagePayRequest request = new AlipayFundTransPagePayRequest();
|
||||
AlipayFundTransPagePayModel model = new AlipayFundTransPagePayModel();
|
||||
//商户端的唯一订单号,对于同一笔转账请求,商户需保证该订单号唯一。
|
||||
model.setOutBizNo("AQF_ZZ_" + SeqKit.genTransOrderId());
|
||||
log.info("资金专款拨入outBizNo=====================" + model.getOutBizNo());
|
||||
//拨入总金额,单位为元,精确到小数点后两位,取值范围[0.01,9999999999999.99]
|
||||
model.setTransAmount(transAmount);
|
||||
//
|
||||
model.setProductCode("FUND_ACCOUNT_BOOK");
|
||||
//
|
||||
model.setBizScene("SATF_DEPOSIT");
|
||||
//充值订单过期时间,默认会失败
|
||||
model.setTimeExpire(formattedDateTime);
|
||||
//收款方信息
|
||||
Participant payeeInfo = new Participant();
|
||||
//记账本 id
|
||||
payeeInfo.setIdentity(subjectEntity.getTransChannelMchNo());
|
||||
payeeInfo.setIdentityType("ACCOUNT_BOOK_ID");
|
||||
//传入记账本id与场景码,不传会校验失败导致充值失败。协议字段必传。
|
||||
JSONObject parm = new JSONObject();
|
||||
parm.put("agreement_no", subjectEntity.getTransChannelSignNo());
|
||||
payeeInfo.setExtInfo(parm.toJSONString());
|
||||
model.setPayeeInfo(payeeInfo);
|
||||
|
||||
request.setBizModel(model);
|
||||
|
||||
AlipayFundTransPagePayResponse response = alipayClient.pageExecute(request, "GET");
|
||||
if (response.isSuccess()) {
|
||||
log.info("资金专项拨入结果:" + response.getBody());
|
||||
resultUrl = response.getBody();
|
||||
//转账中,回调后改变状态
|
||||
transferOrder.setState(TransferOrderEntity.STATE_ING);
|
||||
} else {
|
||||
log.error("资金专项拨入失败!" + response.getSubMsg());
|
||||
resultUrl = response.getSubMsg();
|
||||
//转账失败
|
||||
transferOrder.setState(TransferOrderEntity.STATE_FAIL);
|
||||
transferOrder.setErrCode(response.getSubCode());
|
||||
transferOrder.setErrMsg(response.getSubMsg());
|
||||
}
|
||||
//将订单信息入库
|
||||
// TODO: 2024/4/29 先做简单入库 后续完善
|
||||
transferOrder.setAmount(AmountUtil.convertDollar2CentLong(transAmount));
|
||||
transferOrder.setTransferId(model.getOutBizNo());
|
||||
transferOrder.setMchOrderNo(model.getOutBizNo());
|
||||
transferOrder.setTransferType(TransferOrderEntity.TRANSFER_TYPE_ZZ);
|
||||
transferOrder.setTransferSubjectIdFq(subjectEntity.getId());
|
||||
transferOrder.setTransferSubjectIdJs(subjectEntity.getId());
|
||||
transferOrder.setMchNo(subjectEntity.getMchNo());
|
||||
transferOrder.setMchExtNo(StringUtils.isNotEmpty(subjectEntity.getMchApplyId())?subjectEntity.getMchApplyId():null);
|
||||
transferOrder.setAgentNo(subjectEntity.getAgentNo());
|
||||
transferOrder.setAccountNo(subjectEntity.getAccount());
|
||||
transferOrder.setAccountName(subjectEntity.getAccountName());
|
||||
transferOrder.setTransferDesc(StringUtils.isNotEmpty(transferDesc)?transferDesc:null);
|
||||
transferOrderService.save(transferOrder);
|
||||
} catch (Exception e) {
|
||||
log.error("资金专项拨入异常!",e);
|
||||
throw new BizException("资金专项拨入异常!");
|
||||
}
|
||||
}
|
||||
|
||||
return resultUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于记账本代发
|
||||
*/
|
||||
@Override
|
||||
public ChannelRetMsg transUniTransfer(TransferOrder transferOrder) {
|
||||
log.info("进入了支付宝代发!");
|
||||
ChannelRetMsg retMsg = ChannelRetMsg.waiting();
|
||||
CertAlipayRequest certAlipayRequest = getCertAliPayRequest(transferOrder.getIsvNo());
|
||||
TransferSubjectEntity ersubjectEntity = transferSubjectService.getById(transferOrder.getTransferSubjectIdFq());
|
||||
TransferSubjectEntity eesubjectEntity = transferSubjectService.getById(transferOrder.getTransferSubjectIdJs());
|
||||
try {
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
|
||||
AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
|
||||
AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
|
||||
|
||||
model.setOutBizNo(transferOrder.getTransferId());
|
||||
model.setTransAmount(AmountUtil.convertCent2Dollar(transferOrder.getAmount()));
|
||||
model.setProductCode("SINGLE_TRANSFER_NO_PWD");
|
||||
model.setBizScene("ENTRUST_TRANSFER");
|
||||
model.setOrderTitle(StringUtils.isNotEmpty(transferOrder.getTransferDesc()) ? transferOrder.getTransferDesc() : "支付宝代发到户!");
|
||||
//付款方信息
|
||||
Participant participanter = new Participant();
|
||||
participanter.setIdentity(ersubjectEntity.getTransChannelMchNo());
|
||||
participanter.setIdentityType("ACCOUNT_BOOK_ID");
|
||||
JSONObject erparm = new JSONObject();
|
||||
erparm.put("agreement_no", ersubjectEntity.getTransChannelSignNo());
|
||||
participanter.setExtInfo(erparm.toJSONString());
|
||||
model.setPayerInfo(participanter);
|
||||
//收款方信息
|
||||
Participant participantee = new Participant();
|
||||
participantee.setIdentity(eesubjectEntity.getAccount());
|
||||
if (TransferOrderEntity.ENTRY_ALIPAY_CASH.equals(transferOrder.getEntryType())){
|
||||
participantee.setIdentityType("ALIPAY_LOGON_ID");
|
||||
participantee.setName(eesubjectEntity.getAccountName());
|
||||
}else if (TransferOrderEntity.ENTRY_BANK_CARD.equals(transferOrder.getEntryType())){
|
||||
participantee.setIdentityType("BANKCARD_ACCOUNT");
|
||||
BankcardExtInfo bankcardExtInfo = new BankcardExtInfo();
|
||||
participantee.setName(eesubjectEntity.getAccountName());
|
||||
if (eesubjectEntity.getAccountType() == TransferBasicInfo.ACCOUNT_TYPE_COR) {
|
||||
//对公
|
||||
String accountMessage = eesubjectEntity.getAccountMessage();
|
||||
if (StringUtils.isNotEmpty(accountMessage)) {
|
||||
JSONObject jsonObject = JSONObject.parseObject(accountMessage);
|
||||
bankcardExtInfo.setAccountType("1");
|
||||
bankcardExtInfo.setInstName(jsonObject.getString("instName"));
|
||||
bankcardExtInfo.setInstProvince(jsonObject.getString("instProvince"));
|
||||
bankcardExtInfo.setInstCity(jsonObject.getString("instCity"));
|
||||
bankcardExtInfo.setInstBranchName(jsonObject.getString("instBranchName"));
|
||||
participantee.setBankcardExtInfo(bankcardExtInfo);
|
||||
transferOrder.setBankName(jsonObject.getString("instName"));
|
||||
}
|
||||
} else {
|
||||
//对私
|
||||
bankcardExtInfo.setAccountType("2");
|
||||
participantee.setBankcardExtInfo(bankcardExtInfo);
|
||||
}
|
||||
}
|
||||
model.setPayeeInfo(participantee);
|
||||
request.setBizModel(model);
|
||||
AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request);
|
||||
retMsg.setChannelAttach(response.getBody());
|
||||
if (response.isSuccess()) {
|
||||
retMsg.setChannelOrderId(response.getOrderId());
|
||||
retMsg.setPlatformOrderNo(response.getPayFundOrderId());
|
||||
} else {
|
||||
retMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
retMsg.setChannelErrMsg(response.getSubMsg());
|
||||
retMsg.setChannelErrCode(response.getSubCode());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.info("代发异常!",e);
|
||||
retMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
retMsg.setChannelErrMsg(e.getMessage());
|
||||
}
|
||||
return retMsg;
|
||||
}
|
||||
/**
|
||||
* 账单查询
|
||||
*/
|
||||
|
||||
@Override
|
||||
public JSONObject bizfundagentQuery(String subId, String startTime, String endTime, String pageNo, String pageSize) {
|
||||
log.info("进入了支付宝账单查询");
|
||||
TransferSubjectEntity ersubjectEntity = getSubjectOne(subId);
|
||||
CertAlipayRequest certAlipayRequest = getCertAliPayRequest(ersubjectEntity.getIsvNo());
|
||||
JSONObject resut = new JSONObject();
|
||||
AlipayDataBillBizfundagentQueryResponse response = new AlipayDataBillBizfundagentQueryResponse();
|
||||
if ( ersubjectEntity.getTransChannelSignNo() == null || ersubjectEntity.getTransChannelMchNo() == null) {
|
||||
throw new BizException("当前付款人签约或开通记账本!");
|
||||
}
|
||||
try {
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
|
||||
AlipayDataBillBizfundagentQueryRequest request = new AlipayDataBillBizfundagentQueryRequest();
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("start_time", startTime);
|
||||
jsonObject.put("end_time", endTime);
|
||||
jsonObject.put("page_no", StringUtils.isEmpty(pageNo) ? "1" : pageNo);
|
||||
jsonObject.put("page_size", StringUtils.isEmpty(pageSize) ? "2000" : pageSize);
|
||||
jsonObject.put("agreement_no", ersubjectEntity.getTransChannelSignNo());
|
||||
jsonObject.put("account_book_id", ersubjectEntity.getTransChannelMchNo());
|
||||
request.setBizContent(jsonObject.toJSONString());
|
||||
|
||||
response = alipayClient.certificateExecute(request);
|
||||
if (response.isSuccess()) {
|
||||
log.info("安全发账单查询成功:" + response.getBody());
|
||||
} else {
|
||||
log.error("安全发账单查询失败!" + response.getSubMsg());
|
||||
}
|
||||
resut = JSONObject.parseObject(response.getBody()).getJSONObject("alipay_data_bill_bizfundagent_query_response");
|
||||
} catch (Exception e) {
|
||||
resut.put("code", "99999");
|
||||
resut.put("subMsg", "安全发账单查询异常!!");
|
||||
log.error("安全发账单查询异常!",e);
|
||||
}
|
||||
return resut;
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请电子回单
|
||||
*/
|
||||
|
||||
@Override
|
||||
public JSONObject applicationForm(String subId, String transferId) {
|
||||
log.info("进入了支付宝申请电子回单");
|
||||
TransferSubjectEntity ersubjectEntity = getSubjectOne(subId);
|
||||
CertAlipayRequest certAlipayRequest = getCertAliPayRequest(ersubjectEntity.getIsvNo());
|
||||
TransferOrderEntity transferOrder = transferOrderService.getById(transferId);
|
||||
JSONObject resut = new JSONObject();
|
||||
AlipayDataBillEreceiptagentApplyResponse response;
|
||||
if (ersubjectEntity.getTransChannelSignNo() == null || transferOrder == null || transferOrder.getFlowNo() == null) {
|
||||
throw new BizException("当前付款人不符合申请条件!");
|
||||
}
|
||||
try {
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
|
||||
AlipayDataBillEreceiptagentApplyRequest request = new AlipayDataBillEreceiptagentApplyRequest();
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("type", "FUND_DETAIL");
|
||||
jsonObject.put("key", transferOrder.getFlowNo());
|
||||
jsonObject.put("agreement_no", ersubjectEntity.getTransChannelSignNo());
|
||||
request.setBizContent(jsonObject.toJSONString());
|
||||
|
||||
response = alipayClient.certificateExecute(request);
|
||||
if (response.isSuccess()) {
|
||||
log.info("申请电子回单:" + response.getBody());
|
||||
transferOrder.setApplicationFormState(1);
|
||||
transferOrder.setApplicationFileId(response.getFileId());
|
||||
transferOrderService.updateById(transferOrder);
|
||||
} else {
|
||||
log.error("申请电子回单失败!" + response.getSubMsg());
|
||||
}
|
||||
resut = JSONObject.parseObject(response.getBody()).getJSONObject("alipay_data_bill_ereceiptagent_apply_response");
|
||||
} catch (Exception e) {
|
||||
resut.put("code", "99999");
|
||||
resut.put("subMsg", "申请电子回单异常!!");
|
||||
log.error("申请电子回单异常!",e);
|
||||
}
|
||||
return resut;
|
||||
}
|
||||
|
||||
/**
|
||||
* 回单申请状态和下载地址
|
||||
*/
|
||||
|
||||
@Override
|
||||
public JSONObject applicationFormDownload(String subId, String transferId) {
|
||||
log.info("进入了支付宝回单申请状态和下载地址");
|
||||
TransferSubjectEntity ersubjectEntity = getSubjectOne(subId);
|
||||
CertAlipayRequest certAlipayRequest = getCertAliPayRequest(ersubjectEntity.getIsvNo());
|
||||
TransferOrderEntity transferOrder = transferOrderService.getById(transferId);
|
||||
JSONObject resut = new JSONObject();
|
||||
|
||||
AlipayDataBillAccountbookereceiptQueryResponse response;
|
||||
if (ersubjectEntity.getTransChannelSignNo() == null || transferOrder == null || transferOrder.getApplicationFileId() == null) {
|
||||
throw new BizException("当前付款人不符合申请条件!");
|
||||
}
|
||||
|
||||
try {
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
|
||||
AlipayDataBillAccountbookereceiptQueryRequest request = new AlipayDataBillAccountbookereceiptQueryRequest();
|
||||
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("file_id", transferOrder.getApplicationFileId());
|
||||
jsonObject.put("agreement_no", ersubjectEntity.getTransChannelSignNo());
|
||||
request.setBizContent(jsonObject.toJSONString());
|
||||
response = alipayClient.certificateExecute(request);
|
||||
if (response.isSuccess()) {
|
||||
log.info("回单申请状态和下载地址返回:" + response.getBody());
|
||||
} else {
|
||||
log.error("回单申请状态和下载地址失败!" + response.getSubMsg());
|
||||
}
|
||||
resut = JSONObject.parseObject(response.getBody()).getJSONObject("alipay_data_bill_accountbookereceipt_query_response");
|
||||
} catch (Exception e) {
|
||||
resut.put("code", "99999");
|
||||
resut.put("subMsg", "回单申请状态和下载地址异常!!");
|
||||
log.error("回单申请状态和下载地址异常!",e);
|
||||
}
|
||||
return resut;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成待发待结算信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String settlementData(String ersubId, List<TransferOrder> entityList, String taskId, String entryType, String accountType) {
|
||||
String resut = "操作成功!";
|
||||
TransferSubjectEntity transferSubject = transferSubjectService.getById(ersubId);
|
||||
if (transferSubject.getState() == TransferSubject.STATE_DISABLE) {
|
||||
throw new BizException("当前付款账户已停用!");
|
||||
}
|
||||
if (ObjUtil.isEmpty(entityList)) {
|
||||
throw new BizException("收款人不能为空!");
|
||||
}
|
||||
if (transferSubject.getTransChannelMchNo() == null || transferSubject.getTransChannelSignNo() == null) {
|
||||
throw new BizException("付款账户暂未签约或开通记账本!");
|
||||
}
|
||||
TaskList task = taskListService.getById(taskId);
|
||||
//先进行手续费账户余额校验
|
||||
long total = 0;
|
||||
for (TransferOrder transferOrder : entityList) {
|
||||
long transAmountInCent = AmountUtil.convertDollar2CentLong(transferOrder.getTransAmount()); // 将金额转换为以分为单位
|
||||
total += transAmountInCent ;//累加转化后的金额
|
||||
}
|
||||
|
||||
String infoId;
|
||||
if (CS.SYS_ROLE_TYPE.AGENT.equals(transferSubject.getInfoType())) {
|
||||
infoId = transferSubject.getAgentNo();
|
||||
} else {
|
||||
infoId = transferSubject.getMchNo();
|
||||
}
|
||||
|
||||
accountInfoService.checkBalance(infoId, AccountInfo.Type.SERVICE_CHARGE, total);
|
||||
Map<String, TransferSubject> map = new HashMap<>();
|
||||
for (TransferOrder item: entityList) {
|
||||
TransferSubject itemJsInfo = map.get(item.getTransferSubjectIdJs());
|
||||
if (itemJsInfo == null) {
|
||||
itemJsInfo = transferSubjectService.getById(item.getTransferSubjectIdJs());
|
||||
map.put(item.getTransferSubjectIdJs(), itemJsInfo);
|
||||
}
|
||||
|
||||
// ersubId:付款方id eesubId:收款方id
|
||||
// TODO: 2024/4/30 后续完善参数
|
||||
TransferOrderEntity transferOrder = transferConverter.toDbEntity(item);
|
||||
transferOrder.setTransferId("AQF_ZZ_" + SeqKit.genTransOrderId());
|
||||
transferOrder.setMchNo(transferSubject.getMchNo());
|
||||
transferOrder.setMchExtNo(transferSubject.getMchApplyId());
|
||||
transferOrder.setIsvNo(transferSubject.getIsvNo());
|
||||
transferOrder.setAgentNo(transferSubject.getAgentNo());
|
||||
transferOrder.setTaskId(taskId);
|
||||
transferOrder.setTransferSubjectIdFq(ersubId);
|
||||
transferOrder.setTransferSubjectIdJs(item.getTransferSubjectIdJs());
|
||||
transferOrder.setAccountType(accountType);
|
||||
transferOrder.setTaskId(task.getId());
|
||||
transferOrder.setTaskName(task.getTaskName());
|
||||
transferOrder.setAccountNo(itemJsInfo.getAccount());
|
||||
transferOrder.setAccountName(itemJsInfo.getAccountName());
|
||||
transferOrder.setOriginAccountNo(transferSubject.getAccount());
|
||||
transferOrder.setOriginAccountName(transferSubject.getAccountName());
|
||||
Long transAmount = AmountUtil.convertDollar2CentLong(item.getTransAmount());
|
||||
transferOrder.setIfCode(CS.IF_CODE.ALIAQF);
|
||||
transferOrder.setAmount(transAmount);
|
||||
transferOrder.setEntryType(entryType);
|
||||
Map<String, PaywayFee> paywayFeeMap = rateConfigService.queryPaywayFeeMap(RateConfig.appendInfoByMchApp(transferSubject.getMchNo()), CS.SYS_ROLE_TYPE.MCH, transferSubject.getTransIfCode(), null, null, transferSubject.getIsvNo(), true);
|
||||
if(paywayFeeMap == null){
|
||||
throw new BizException("转账费率信息异常");
|
||||
}
|
||||
PaywayFee paywayFee = paywayFeeMap.get(transferOrder.getEntryType());
|
||||
if(paywayFee == null){
|
||||
throw new BizException("未获取到指定的打款方式的费率信息");
|
||||
}
|
||||
MutablePair<String, Long> feeAndSnapshot = paywayFee.calFeeAndSnapshot(transAmount);
|
||||
transferOrder.setFeeCostType(TransferOrder.COST_TYPE_ACCOUNT);
|
||||
transferOrder.setMchFeeRate(feeAndSnapshot.left);
|
||||
transferOrder.setMchOrderFeeAmount(feeAndSnapshot.right);
|
||||
transferOrder.setTransferDesc(item.getTransferDesc());
|
||||
if (StringUtils.isNotEmpty(item.getBatchId())) {
|
||||
transferOrder.setBatchId(item.getBatchId());
|
||||
}
|
||||
transferOrder.setTransferType(TransferOrderEntity.TRANSFER_TYPE_DF);
|
||||
transferOrderService.save(transferOrder);
|
||||
}
|
||||
return resut;
|
||||
}
|
||||
|
||||
public CertAlipayRequest getCertAliPayRequest(String isvNo) {
|
||||
TransferInterfaceConfigEntity transferInterfaceConfigEntity = transferInterfaceConfigService.getTransferConfig(CS.IF_CODE.ALIAQF, isvNo, CS.SYS_ROLE_TYPE.ISV);
|
||||
Assert.notNull(transferInterfaceConfigEntity, "所选渠道配置不存在");
|
||||
|
||||
CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
|
||||
ChannelCertConfigKitBean channelCertConfigKitBean = SpringBeansUtil.getBean(ChannelCertConfigKitBean.class);
|
||||
AliaqfIsvParams isvParams = JSONObject.parseObject(transferInterfaceConfigEntity.getTransIfParams(), AliaqfIsvParams.class);
|
||||
// 支付宝网关
|
||||
certAlipayRequest.setServerUrl(AlipayConfig.PROD_SERVER_URL);
|
||||
certAlipayRequest.setAppId(isvParams.getAppId());
|
||||
certAlipayRequest.setPrivateKey(isvParams.getPrivateKey());
|
||||
certAlipayRequest.setCertPath(channelCertConfigKitBean.getCertFilePath(isvParams.getAppPublicCert()));
|
||||
certAlipayRequest.setAlipayPublicCertPath(channelCertConfigKitBean.getCertFilePath(isvParams.getAlipayPublicCert()));
|
||||
certAlipayRequest.setRootCertPath(channelCertConfigKitBean.getCertFilePath(isvParams.getAlipayRootCert()));
|
||||
certAlipayRequest.setSignType("RSA2");
|
||||
certAlipayRequest.setFormat("json");
|
||||
certAlipayRequest.setCharset("UTF-8");
|
||||
|
||||
return certAlipayRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据付款人信息id获取详情
|
||||
*/
|
||||
public TransferSubjectEntity getSubjectOne(String subId){
|
||||
TransferSubjectEntity transferSubjectEntity = transferSubjectService.getById(subId);
|
||||
if (transferSubjectEntity != null){
|
||||
return transferSubjectEntity;
|
||||
}else {
|
||||
throw new BizException("未查询到当前付款人信息!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.converter.TransferConverter;
|
||||
import com.jeequan.jeepay.core.beans.RequestKitBean;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.TransferOrder;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.db.entity.TransferOrderEntity;
|
||||
import com.jeequan.jeepay.service.impl.TransferOrderService;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractTransferNoticeService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @author deng
|
||||
* @since 2024/5/8
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AliaqfTransferNoticeService extends AbstractTransferNoticeService {
|
||||
|
||||
@Autowired
|
||||
private RequestKitBean requestKitBean;
|
||||
|
||||
@Autowired
|
||||
private TransferOrderService transferOrderService;
|
||||
|
||||
@Autowired
|
||||
private TransferConverter transferConverter;
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.ALIAQF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlOrderId) {
|
||||
JSONObject reqParamJSON = requestKitBean.getReqParamJSON();
|
||||
log.info("【支付宝安全发接口回调】, 原始参数为{}", reqParamJSON);
|
||||
|
||||
String input = reqParamJSON.getString("input");
|
||||
if (ObjUtil.isEmpty(input)) {
|
||||
return new MutablePair<>();
|
||||
}
|
||||
|
||||
String[] params = input.split("&");
|
||||
|
||||
JSONObject decryptParam = new JSONObject();
|
||||
for (String paramItem : params) {
|
||||
String[] real = paramItem.split("=");
|
||||
if (real.length != 2) {
|
||||
log.info("回调参数格式不正确, {}", paramItem);
|
||||
return new MutablePair<>();
|
||||
}
|
||||
|
||||
try {
|
||||
decryptParam.put(URLDecoder.decode(real[0], "UTF-8"),URLDecoder.decode(real[1], "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.error("参数解析异常, {}", real[1], e);
|
||||
}
|
||||
}
|
||||
|
||||
JSONObject bizContent = decryptParam.getJSONObject("biz_content");
|
||||
log.info("【支付宝安全发接口回调】, 解密后业务参数为{}", bizContent);
|
||||
|
||||
String outBizNo = bizContent.getString("out_biz_no");
|
||||
return new MutablePair<>(outBizNo, bizContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg doNotice(HttpServletRequest request, Object params, TransferOrder transferOrder) {
|
||||
JSONObject bizContent = ((JSONObject) params);
|
||||
ChannelRetMsg result = new ChannelRetMsg();
|
||||
result.setChannelOrderId(bizContent.getString("order_id"));
|
||||
result.setPlatformOrderNo(bizContent.getString("pay_fund_order_id"));
|
||||
result.setChannelOriginResponse(bizContent.toJSONString());
|
||||
switch (bizContent.getString("status")){
|
||||
case "SUCCESS" :
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
break;
|
||||
case "CLOSED" :
|
||||
case "FAIL" :
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
result.setChannelErrMsg(bizContent.getString("sub_order_fail_reason"));
|
||||
break;
|
||||
default:
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
transferOrder.setState(TransferOrderEntity.STATE_ING);
|
||||
break;
|
||||
}
|
||||
|
||||
ResponseEntity<Object> ok = ResponseEntity.ok(retOk(null));
|
||||
result.setResponseEntity(ok);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.text.csv.CsvData;
|
||||
import cn.hutool.core.text.csv.CsvRow;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alipay.api.domain.AlipayDataDataserviceBillDownloadurlQueryModel;
|
||||
import com.alipay.api.request.AlipayDataDataserviceBillDownloadurlQueryRequest;
|
||||
import com.alipay.api.response.AlipayDataDataserviceBillDownloadurlQueryResponse;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.CheckBatch;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.bill.ChannelBill;
|
||||
import com.jeequan.jeepay.core.model.bill.ChannelBillRQ;
|
||||
import com.jeequan.jeepay.core.model.bill.ChannelBillRS;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvsubMchParams;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.core.utils.ExcelUtil;
|
||||
import com.jeequan.jeepay.db.entity.CheckChannelBill;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractBillDownloadService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
/*
|
||||
* 支付宝 对账单下载
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2021/6/8 17:20
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AlipayBillDownloadService extends AbstractBillDownloadService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.ALIPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelBillRS convertStandardBill(ChannelBillRQ channelBillRQ, MchAppConfigContext mchAppConfigContext, Date billDate, String ifCode){
|
||||
|
||||
String logPrefix = "【支付宝对账单下载】";
|
||||
|
||||
ChannelBillRS channelBillRes = new ChannelBillRS();
|
||||
|
||||
AlipayDataDataserviceBillDownloadurlQueryRequest req = new AlipayDataDataserviceBillDownloadurlQueryRequest();
|
||||
AlipayDataDataserviceBillDownloadurlQueryModel model = new AlipayDataDataserviceBillDownloadurlQueryModel();
|
||||
req.setBizModel(model);
|
||||
|
||||
model.setBillDate(DateUtil.formatDate(billDate));
|
||||
model.setBillType("trade");
|
||||
|
||||
String channelMchNo = channelBillRQ.getChannelMchNo(); // 渠道商户号
|
||||
|
||||
// 特约商户, 放置子商户token
|
||||
if(mchAppConfigContext.isIsvsubMch()){
|
||||
AlipayIsvsubMchParams isvsubMchParams = (AlipayIsvsubMchParams) channelBillRQ.getIsvsubMchParams();
|
||||
req.putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
}
|
||||
|
||||
// 账单文件流
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
|
||||
try {
|
||||
AlipayDataDataserviceBillDownloadurlQueryResponse resp = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).execute(req);
|
||||
log.info("{},返回结果:{}", logPrefix, JSON.toJSONString(resp));
|
||||
if (!resp.isSuccess()) {
|
||||
throw new BizException(resp.getCode() + "[" + resp.getMsg() + "]," + resp.getSubCode() + "[" + resp.getSubMsg() + "]");
|
||||
}
|
||||
|
||||
// 下载对账单,写入文件输出流
|
||||
HttpUtil.download(resp.getBillDownloadUrl(), byteArrayOutputStream, false);
|
||||
|
||||
// 上传oss
|
||||
String url = upload2Oss(ifCode, channelMchNo, billDate, ".zip", IoUtil.toStream(byteArrayOutputStream));
|
||||
// 生成附带对账文件下载地址的解析成功的批次
|
||||
CheckBatch checkBatch = genReleaseSuccessCheckBatch(ifCode, billDate, channelMchNo, url);
|
||||
// 渠道账单列表
|
||||
List<ChannelBill> channelBillList = new ArrayList<>();
|
||||
// 渠道总退款金额
|
||||
long channelTotalRefundAmount = 0;
|
||||
|
||||
// 读取对账单 csv文件
|
||||
List<MutablePair<ZipEntry, CsvData>> mutablePairs = ExcelUtil.readCsvDataByZipInputStream(IoUtil.toStream(byteArrayOutputStream), CharsetUtil.CHARSET_GBK, CharsetUtil.CHARSET_GBK);
|
||||
|
||||
for (MutablePair<ZipEntry, CsvData> mutablePair : mutablePairs) {
|
||||
CsvData data = mutablePair.right;
|
||||
List<CsvRow> rows = data.getRows();
|
||||
|
||||
// 汇总数据
|
||||
if (mutablePair.left.getName().contains("汇总")) {
|
||||
if (rows.size() > 1) {
|
||||
List<String> rawList = rows.get(1).getRawList();
|
||||
|
||||
if (rawList.size() > 10) {
|
||||
checkBatch.setChannelTotalCount(Integer.valueOf(rawList.get(2).trim()));
|
||||
checkBatch.setChannelTotalRefundCount(Integer.valueOf(rawList.get(3).trim()));
|
||||
checkBatch.setChannelTotalAmount(AmountUtil.convertDollar2CentLong(rawList.get(4).trim()));
|
||||
checkBatch.setChannelTotalFee(AmountUtil.convertDollar2CentLong(rawList.get(9).trim()));
|
||||
}
|
||||
}
|
||||
|
||||
// 明细数据
|
||||
}else{
|
||||
// 遍历行
|
||||
for (int i = 1; i < rows.size(); i++) {
|
||||
CsvRow csvRow = rows.get(i);
|
||||
// getRawList返回一个List列表,列表的每一项为CSV中的一个单元格
|
||||
List<String> rawList = csvRow.getRawList();
|
||||
|
||||
if (rawList.size() > 22) {
|
||||
ChannelBill channelBill = new ChannelBill();
|
||||
channelBill.setBatchNo(checkBatch.getBatchNo());
|
||||
channelBill.setBillDate(billDate);
|
||||
channelBill.setIfCode(ifCode);
|
||||
channelBill.setChannelMchNo(channelMchNo);
|
||||
channelBill.setChannelOrderNo(rawList.get(0).trim());
|
||||
channelBill.setChannelAmount(Math.abs(AmountUtil.convertDollar2CentLong(rawList.get(11).trim())));
|
||||
channelBill.setChannelFeeAmount(Math.abs(AmountUtil.convertDollar2CentLong(rawList.get(22).trim())));
|
||||
channelBill.setChannelSuccessAt(DateUtil.parseDateTime(rawList.get(5).trim()));
|
||||
channelBill.setChannelUser(rawList.get(10).trim());
|
||||
|
||||
if (StringUtils.equals(rawList.get(2).trim(), "交易")) {
|
||||
channelBill.setOrderId(rawList.get(1).trim());
|
||||
channelBill.setBillType(CheckChannelBill.BILL_TYPE_PAY);
|
||||
channelBill.setChannelState((byte) 2);
|
||||
}else if (StringUtils.equals(rawList.get(2).trim(), "退款")) {
|
||||
channelBill.setOrderId(rawList.get(21).trim()); // 平台退款订单号
|
||||
channelBill.setBillType(CheckChannelBill.BILL_TYPE_REFUND);
|
||||
channelBill.setChannelState((byte) 5);
|
||||
channelBill.setOrgPayOrderId(rawList.get(1).trim());
|
||||
|
||||
channelTotalRefundAmount += channelBill.getChannelAmount();
|
||||
}else {
|
||||
log.error("支付宝账单类型错误!");
|
||||
continue;
|
||||
}
|
||||
|
||||
channelBillList.add(channelBill);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkBatch.setChannelTotalRefundAmount(channelTotalRefundAmount);
|
||||
checkBatch.setChannelTotalAmount(checkBatch.getChannelTotalAmount() + Math.abs(channelTotalRefundAmount));
|
||||
|
||||
channelBillRes.setCheckBatch(checkBatch);
|
||||
channelBillRes.setChannelBillList(channelBillList);
|
||||
|
||||
return channelBillRes;
|
||||
}catch (Exception e) {
|
||||
log.error("{}, 解析对账文件失败,", logPrefix, e);
|
||||
channelBillRes.setCheckBatch(genReleaseFailCheckBatch(ifCode, billDate, channelMchNo, e.getMessage()));
|
||||
return channelBillRes;
|
||||
}finally {
|
||||
IoUtil.close(byteArrayOutputStream);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alipay.api.internal.util.AlipaySignature;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.ResponseException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayConfig;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayNormalMchParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractChannelNoticeService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
/*
|
||||
* 支付宝 回调接口实现类
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:20
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AlipayChannelNoticeService extends AbstractChannelNoticeService {
|
||||
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.ALIPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlOrderId, NoticeTypeEnum noticeTypeEnum) {
|
||||
|
||||
try {
|
||||
|
||||
JSONObject params = getReqParamJSON();
|
||||
String payOrderId = params.getString("out_trade_no");
|
||||
return MutablePair.of(payOrderId, params);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("error", e);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg doNotice(HttpServletRequest request, Object params, PayOrder payOrder, MchAppConfigContext mchAppConfigContext, NoticeTypeEnum noticeTypeEnum) {
|
||||
try {
|
||||
|
||||
//配置参数获取
|
||||
Byte useCert = null;
|
||||
String alipaySignType, alipayPublicCert, alipayPublicKey = null;
|
||||
if(mchAppConfigContext.isIsvsubMch()){
|
||||
|
||||
// 获取支付参数
|
||||
AlipayIsvParams alipayParams = (AlipayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment().getIsvNo(), getIfCode());
|
||||
useCert = alipayParams.getUseCert();
|
||||
alipaySignType = alipayParams.getSignType();
|
||||
alipayPublicCert = alipayParams.getAlipayPublicCert();
|
||||
alipayPublicKey = alipayParams.getAlipayPublicKey();
|
||||
|
||||
}else{
|
||||
|
||||
// 获取支付参数
|
||||
AlipayNormalMchParams alipayParams = (AlipayNormalMchParams)configContextQueryService.queryNormalMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), getIfCode());
|
||||
|
||||
useCert = alipayParams.getUseCert();
|
||||
alipaySignType = alipayParams.getSignType();
|
||||
alipayPublicCert = alipayParams.getAlipayPublicCert();
|
||||
alipayPublicKey = alipayParams.getAlipayPublicKey();
|
||||
}
|
||||
|
||||
// 获取请求参数
|
||||
JSONObject jsonParams = (JSONObject) params;
|
||||
|
||||
boolean verifyResult;
|
||||
if(useCert != null && useCert == CS.YES){ //证书方式
|
||||
|
||||
verifyResult = AlipaySignature.rsaCertCheckV1(jsonParams.toJavaObject(Map.class), getCertFilePath(alipayPublicCert),
|
||||
AlipayConfig.CHARSET, alipaySignType);
|
||||
|
||||
}else{
|
||||
verifyResult = AlipaySignature.rsaCheckV1(jsonParams.toJavaObject(Map.class), alipayPublicKey, AlipayConfig.CHARSET, alipaySignType);
|
||||
}
|
||||
|
||||
//验签失败
|
||||
if(!verifyResult){
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
|
||||
//验签成功后判断上游订单状态
|
||||
ResponseEntity okResponse = textResp("SUCCESS");
|
||||
|
||||
ChannelRetMsg result = new ChannelRetMsg();
|
||||
result.setChannelOrderId(jsonParams.getString("trade_no")); //渠道订单号
|
||||
result.setPlatformOrderNo(jsonParams.getString("trade_no"));
|
||||
result.setPlatformMchOrderNo(payOrder.getPayOrderId());
|
||||
result.setChannelUserId(jsonParams.getString("buyer_id")); //支付用户ID
|
||||
result.setResponseEntity(okResponse); //响应数据
|
||||
result.setChannelBizData(jsonParams);
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.WAITING); // 默认支付中
|
||||
|
||||
if("TRADE_SUCCESS".equals(jsonParams.getString("trade_status"))){
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
|
||||
}else if("TRADE_CLOSED".equals(jsonParams.getString("trade_status"))){
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("error", e);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alipay.api.domain.*;
|
||||
import com.alipay.api.request.AlipayTradeOrderSettleRequest;
|
||||
import com.alipay.api.request.AlipayTradeRoyaltyRelationBindRequest;
|
||||
import com.alipay.api.response.AlipayTradeOrderSettleResponse;
|
||||
import com.alipay.api.response.AlipayTradeRoyaltyRelationBindResponse;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.*;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.core.utils.RegKit;
|
||||
import com.jeequan.jeepay.core.utils.SeqKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractDivisionService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账接口: 支付宝官方
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/8/22 09:05
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AlipayDivisionService extends AbstractDivisionService {
|
||||
|
||||
@Autowired private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public boolean divisionRefundIsOrderRefundAfterProc() {
|
||||
return true; // 事后分账回退
|
||||
}
|
||||
|
||||
// 分账回退, 默认成功。
|
||||
@Override
|
||||
public ChannelRetMsg divisionRefund(PayOrderDivisionRecord payOrderDivisionRecord, PayOrderDivisionRefundRecord payOrderDivisionRefundRecord, RefundOrder refundOrder, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) {
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.ALIPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupport() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg bind(MchDivisionReceiver mchDivisionReceiver, MchAppConfigContext mchAppConfigContext) {
|
||||
|
||||
try {
|
||||
AlipayTradeRoyaltyRelationBindRequest request = new AlipayTradeRoyaltyRelationBindRequest();
|
||||
AlipayTradeRoyaltyRelationBindModel model = new AlipayTradeRoyaltyRelationBindModel();
|
||||
request.setBizModel(model);
|
||||
model.setOutRequestNo(SeqKit.genDivisionBatchId());
|
||||
|
||||
//统一放置 isv接口必传信息
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, request, model);
|
||||
|
||||
RoyaltyEntity royaltyEntity = new RoyaltyEntity();
|
||||
|
||||
royaltyEntity.setType("loginName");
|
||||
if(RegKit.isAlipayUserId(mchDivisionReceiver.getAccNo())){
|
||||
royaltyEntity.setType("userId");
|
||||
}
|
||||
royaltyEntity.setAccount(mchDivisionReceiver.getAccNo());
|
||||
royaltyEntity.setName(mchDivisionReceiver.getAccName());
|
||||
royaltyEntity.setMemo(mchDivisionReceiver.getRelationTypeName()); //分账关系描述
|
||||
model.setReceiverList(Arrays.asList(royaltyEntity));
|
||||
|
||||
AlipayTradeRoyaltyRelationBindResponse alipayResp = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).execute(request);
|
||||
|
||||
if(alipayResp.isSuccess()){
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}
|
||||
|
||||
//异常:
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrCode(AlipayKit.appendErrCode(alipayResp.getCode(), alipayResp.getSubCode()));
|
||||
channelRetMsg.setChannelErrMsg(AlipayKit.appendErrMsg(alipayResp.getMsg(), alipayResp.getSubMsg()));
|
||||
return channelRetMsg;
|
||||
|
||||
} catch (ChannelException e) {
|
||||
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrCode(e.getChannelRetMsg().getChannelErrCode());
|
||||
channelRetMsg.setChannelErrMsg(e.getChannelRetMsg().getChannelErrMsg());
|
||||
return channelRetMsg;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("绑定支付宝账号异常", e);
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrMsg(e.getMessage());
|
||||
return channelRetMsg;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg singleDivision(PayOrder payOrder, List<PayOrderDivisionRecord> recordList, MchAppConfigContext mchAppConfigContext) {
|
||||
|
||||
|
||||
try {
|
||||
|
||||
if(recordList.isEmpty()){ // 当无分账用户时, 支付宝不允许发起分账请求, 支付宝没有完结接口,直接响应成功即可。
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}
|
||||
|
||||
AlipayTradeOrderSettleRequest request = new AlipayTradeOrderSettleRequest();
|
||||
AlipayTradeOrderSettleModel model = new AlipayTradeOrderSettleModel();
|
||||
request.setBizModel(model);
|
||||
|
||||
model.setOutRequestNo(recordList.get(0).getBatchOrderId()); //结算请求流水号,由商家自定义。32个字符以内,仅可包含字母、数字、下划线。需保证在商户端不重复。
|
||||
model.setTradeNo(recordList.get(0).getPayOrderChannelOrderNo()); //支付宝订单号
|
||||
|
||||
//统一放置 isv接口必传信息
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, request, model);
|
||||
|
||||
List<OpenApiRoyaltyDetailInfoPojo> reqReceiverList = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < recordList.size(); i++) {
|
||||
|
||||
PayOrderDivisionRecord record = recordList.get(i);
|
||||
|
||||
if(record.getCalDivisionAmount() <= 0){ //金额为 0 不参与分账处理
|
||||
continue;
|
||||
}
|
||||
|
||||
OpenApiRoyaltyDetailInfoPojo reqReceiver = new OpenApiRoyaltyDetailInfoPojo();
|
||||
reqReceiver.setRoyaltyType("transfer"); //分账类型: 普通分账
|
||||
|
||||
// 出款信息
|
||||
// reqReceiver.setTransOutType("loginName"); reqReceiver.setTransOut("xqxemt4735@sandbox.com");
|
||||
|
||||
// 入款信息
|
||||
reqReceiver.setTransIn(record.getAccNo()); //收入方账号
|
||||
reqReceiver.setTransInType("loginName");
|
||||
if(RegKit.isAlipayUserId(record.getAccNo())){
|
||||
reqReceiver.setTransInType("userId");
|
||||
}
|
||||
// 分账金额
|
||||
reqReceiver.setAmount(AmountUtil.convertCent2Dollar(record.getCalDivisionAmount()));
|
||||
reqReceiver.setDesc("[" + payOrder.getPayOrderId() + "]订单分账");
|
||||
reqReceiverList.add(reqReceiver);
|
||||
|
||||
}
|
||||
|
||||
if(reqReceiverList.isEmpty()){ // 当无分账用户时, 支付宝不允许发起分账请求, 支付宝没有完结接口,直接响应成功即可。
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}
|
||||
|
||||
model.setRoyaltyParameters(reqReceiverList); // 分账明细信息
|
||||
|
||||
// 完结
|
||||
SettleExtendParams settleExtendParams = new SettleExtendParams();
|
||||
settleExtendParams.setRoyaltyFinish("true");
|
||||
model.setExtendParams(settleExtendParams);
|
||||
|
||||
//调起支付宝分账接口
|
||||
if(log.isInfoEnabled()){
|
||||
log.info("订单:[{}], 支付宝分账请求:{}", payOrder.getPayOrderId(), JSON.toJSONString(model));
|
||||
}
|
||||
AlipayTradeOrderSettleResponse alipayResp = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).execute(request);
|
||||
log.info("订单:[{}], 支付宝分账响应:{}", payOrder.getPayOrderId(), alipayResp.getBody());
|
||||
if(alipayResp.isSuccess()){
|
||||
return ChannelRetMsg.confirmSuccess(alipayResp.getTradeNo());
|
||||
}
|
||||
|
||||
//异常:
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrCode(AlipayKit.appendErrCode(alipayResp.getCode(), alipayResp.getSubCode()));
|
||||
channelRetMsg.setChannelErrMsg(AlipayKit.appendErrMsg(alipayResp.getMsg(), alipayResp.getSubMsg()));
|
||||
return channelRetMsg;
|
||||
|
||||
} catch (ChannelException e) {
|
||||
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrCode(e.getChannelRetMsg().getChannelErrCode());
|
||||
channelRetMsg.setChannelErrMsg(e.getChannelRetMsg().getChannelErrMsg());
|
||||
return channelRetMsg;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("绑定支付宝账号异常", e);
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrMsg(e.getMessage());
|
||||
return channelRetMsg;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long queryBalanceAmount(MchDivisionReceiver mchDivisionReceiver, MchAppConfigContext mchAppConfigContext) {
|
||||
throw new BizException("接口不支持");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg cashout(MchDivisionReceiver mchDivisionReceiver, Long amount, MchAppConfigContext mchAppConfigContext) {
|
||||
throw new BizException("接口不支持");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alipay.api.domain.AlipayCommerceIotDeviceBindModel;
|
||||
import com.alipay.api.domain.AlipayCommerceIotDeviceBindQueryModel;
|
||||
import com.alipay.api.domain.AlipayCommerceIotDeviceUnbindModel;
|
||||
import com.alipay.api.request.AlipayCommerceIotDeviceBindQueryRequest;
|
||||
import com.alipay.api.request.AlipayCommerceIotDeviceBindRequest;
|
||||
import com.alipay.api.request.AlipayCommerceIotDeviceUnbindRequest;
|
||||
import com.alipay.api.response.AlipayCommerceIotDeviceBindQueryResponse;
|
||||
import com.alipay.api.response.AlipayCommerceIotDeviceBindResponse;
|
||||
import com.alipay.api.response.AlipayCommerceIotDeviceUnbindResponse;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.alipaybiz.IAlipayIotDeviceBindService;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvParams;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 支付宝Iot设备接口
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2023/3/8 15:13
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AlipayIotDeviceBindService implements IAlipayIotDeviceBindService {
|
||||
|
||||
@Override
|
||||
public void bind(AlipayIsvParams alipayIsvParams, String mchNo, String alipayMerchantNo, String alipayShopId, String supplierId, JSONObject deviceJSON) {
|
||||
AlipayCommerceIotDeviceBindRequest request = new AlipayCommerceIotDeviceBindRequest();
|
||||
AlipayCommerceIotDeviceBindModel model = new AlipayCommerceIotDeviceBindModel();
|
||||
model.setAppType("MINI_APP");
|
||||
model.setMiniAppId("RUYI_LITE");
|
||||
model.setDeviceIdType("SN");
|
||||
model.setDeviceSn(deviceJSON.getString("deviceNo"));
|
||||
model.setSupplierId(supplierId); // 设备供应商ID:
|
||||
model.setExternalId(mchNo); // jeepay商户号
|
||||
model.setMerchantIdType("direct");
|
||||
model.setMerchantId(alipayMerchantNo);
|
||||
model.setShopId(alipayShopId);
|
||||
model.setSource(alipayIsvParams.getPid()); // 受理商户的ISV在支付宝的pid
|
||||
model.setSpiAppId(alipayIsvParams.getAppId()); // 表示ISV在开放平台注册的SPI服务应用的app_id
|
||||
model.setTerminalBindInfo(deviceJSON.toJSONString()); // 由ISV自定义的扩展字段,在支付宝侧向SPI服务发起请求时透传给ISV
|
||||
|
||||
request.setBizModel(model);
|
||||
AlipayCommerceIotDeviceBindResponse response = AlipayKit.getAlipayClientWrapper(alipayIsvParams).getAlipayClient().execute(request);
|
||||
log.info("alipayIot设备绑定响应,deviceNo={},response={}", deviceJSON.getString("deviceNo"), JSONObject.toJSONString(response));
|
||||
if (!response.isSuccess()) {
|
||||
throw new BizException(AlipayKit.appendErrMsg(response.getMsg(), response.getSubMsg()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind(AlipayIsvParams alipayIsvParams, String mchNo, String alipayMerchantNo, String alipayShopId, String supplierId, String deviceSn){
|
||||
AlipayCommerceIotDeviceUnbindRequest request = new AlipayCommerceIotDeviceUnbindRequest();
|
||||
AlipayCommerceIotDeviceUnbindModel model = new AlipayCommerceIotDeviceUnbindModel();
|
||||
model.setAppType("MINI_APP");
|
||||
model.setMiniAppId("RUYI_LITE");
|
||||
model.setDeviceIdType("SN");
|
||||
model.setDeviceSn(deviceSn);
|
||||
model.setSupplierId(supplierId);
|
||||
model.setSource(alipayIsvParams.getPid());
|
||||
model.setExternalId(mchNo); // jeepay商户号 1678169795992
|
||||
model.setMerchantIdType("direct");
|
||||
model.setMerchantId(alipayMerchantNo);
|
||||
model.setShopId(alipayShopId);
|
||||
|
||||
request.setBizModel(model);
|
||||
AlipayCommerceIotDeviceUnbindResponse response = AlipayKit.getAlipayClientWrapper(alipayIsvParams).getAlipayClient().execute(request);
|
||||
log.info("alipayIot设备解绑响应,deviceNo:{},response={}", deviceSn, JSONObject.toJSONString(response));
|
||||
if ("NOT_BIND".equals(response.getSubCode())) {
|
||||
return;
|
||||
}
|
||||
if (!response.isSuccess()) {
|
||||
throw new BizException(AlipayKit.appendErrMsg(response.getMsg(), response.getSubMsg()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject query(AlipayIsvParams alipayIsvParams, String deviceSn){
|
||||
AlipayCommerceIotDeviceBindQueryRequest request = new AlipayCommerceIotDeviceBindQueryRequest();
|
||||
AlipayCommerceIotDeviceBindQueryModel model = new AlipayCommerceIotDeviceBindQueryModel();
|
||||
model.setAppType("MINI_APP");
|
||||
model.setMiniAppId("RUYI_LITE");
|
||||
model.setDeviceIdType("SN");
|
||||
model.setDeviceSn(deviceSn);
|
||||
request.setBizModel(model);
|
||||
|
||||
AlipayCommerceIotDeviceBindQueryResponse response = AlipayKit.getAlipayClientWrapper(alipayIsvParams).getAlipayClient().execute(request);
|
||||
log.info("alipayIot设备查询响应,deviceNo:{},response:{}", deviceSn, JSONObject.toJSONString(response));
|
||||
if (!response.isSuccess()) {
|
||||
throw new BizException(AlipayKit.appendErrMsg(response.getMsg(), response.getSubMsg()));
|
||||
}
|
||||
|
||||
return (JSONObject) JSONObject.toJSON(response);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import com.alipay.api.AlipayObject;
|
||||
import com.alipay.api.AlipayRequest;
|
||||
import com.alipay.api.domain.*;
|
||||
import com.alipay.api.request.*;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvsubMchParams;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.thirdparty.model.AlipayClientWrapper;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/*
|
||||
* 【支付宝】支付通道工具包
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:19
|
||||
*/
|
||||
public class AlipayKit {
|
||||
|
||||
/** 放置 isv特殊信息 **/
|
||||
public static void putApiIsvInfo(MchAppConfigContext mchAppConfigContext, AlipayRequest req, AlipayObject model){
|
||||
|
||||
//不是特约商户, 无需放置此值
|
||||
if(!mchAppConfigContext.isIsvsubMch()){
|
||||
return ;
|
||||
}
|
||||
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
|
||||
// 获取支付参数
|
||||
AlipayIsvParams isvParams = (AlipayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment().getIsvNo(), CS.IF_CODE.ALIPAY);
|
||||
AlipayIsvsubMchParams isvsubMchParams = (AlipayIsvsubMchParams)configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), CS.IF_CODE.ALIPAY);
|
||||
|
||||
// 子商户信息
|
||||
if(req instanceof AlipayTradePayRequest) {
|
||||
((AlipayTradePayRequest)req).putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
} else if(req instanceof AlipayTradeAppPayRequest) {
|
||||
((AlipayTradeAppPayRequest)req).putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
} else if(req instanceof AlipayTradeCreateRequest) {
|
||||
((AlipayTradeCreateRequest)req).putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
} else if(req instanceof AlipayTradePagePayRequest) {
|
||||
((AlipayTradePagePayRequest)req).putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
} else if(req instanceof AlipayTradePrecreateRequest) {
|
||||
((AlipayTradePrecreateRequest)req).putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
} else if(req instanceof AlipayTradeWapPayRequest) {
|
||||
((AlipayTradeWapPayRequest)req).putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
} else if(req instanceof AlipayTradeQueryRequest) {
|
||||
((AlipayTradeQueryRequest)req).putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
} else if(req instanceof AlipayTradeRefundRequest) {
|
||||
((AlipayTradeRefundRequest)req).putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
} else if(req instanceof AlipayTradeFastpayRefundQueryRequest) {
|
||||
((AlipayTradeFastpayRefundQueryRequest)req).putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
} else if(req instanceof AlipayFundTransToaccountTransferRequest) {
|
||||
((AlipayFundTransToaccountTransferRequest)req).putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
} else if(req instanceof AlipayTradeRoyaltyRelationBindRequest) {
|
||||
((AlipayTradeRoyaltyRelationBindRequest)req).putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
} else if(req instanceof AlipayTradeOrderSettleRequest) {
|
||||
((AlipayTradeOrderSettleRequest)req).putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
} else if(req instanceof AlipayDataDataserviceBillDownloadurlQueryRequest) {
|
||||
((AlipayDataDataserviceBillDownloadurlQueryRequest)req).putOtherTextParam("app_auth_token", isvsubMchParams.getAppAuthToken());
|
||||
}
|
||||
|
||||
// 服务商信息
|
||||
ExtendParams extendParams = new ExtendParams();
|
||||
extendParams.setSysServiceProviderId(isvParams.getPid());
|
||||
|
||||
if(model instanceof AlipayTradePayModel) {
|
||||
((AlipayTradePayModel)model).setExtendParams(extendParams);
|
||||
} else if(model instanceof AlipayTradeAppPayModel) {
|
||||
((AlipayTradeAppPayModel)model).setExtendParams(extendParams);
|
||||
} else if(model instanceof AlipayTradeCreateModel) {
|
||||
((AlipayTradeCreateModel)model).setExtendParams(extendParams);
|
||||
} else if(model instanceof AlipayTradePagePayModel) {
|
||||
((AlipayTradePagePayModel)model).setExtendParams(extendParams);
|
||||
} else if(model instanceof AlipayTradePrecreateModel) {
|
||||
((AlipayTradePrecreateModel)model).setExtendParams(extendParams);
|
||||
} else if(model instanceof AlipayTradeWapPayModel) {
|
||||
((AlipayTradeWapPayModel)model).setExtendParams(extendParams);
|
||||
}
|
||||
}
|
||||
|
||||
public static AlipayClientWrapper getAlipayClientWrapper(AlipayIsvParams alipayIsvParams) {
|
||||
return AlipayClientWrapper.buildAlipayClientWrapper(alipayIsvParams, null);
|
||||
}
|
||||
|
||||
|
||||
public static String appendErrCode(String code, String subCode){
|
||||
return StringUtils.defaultIfEmpty(subCode, code); //优先: subCode
|
||||
}
|
||||
|
||||
public static String appendErrMsg(String msg, String subMsg){
|
||||
|
||||
String result = null;
|
||||
if(StringUtils.isNotEmpty(msg) && StringUtils.isNotEmpty(subMsg) ){
|
||||
result = msg + "【" + subMsg + "】";
|
||||
}else{
|
||||
result = StringUtils.defaultIfEmpty(subMsg, msg);
|
||||
}
|
||||
return CharSequenceUtil.maxLength(result, 253);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alipay.api.FileItem;
|
||||
import com.alipay.api.domain.AlipayOpenAgentConfirmModel;
|
||||
import com.alipay.api.domain.AlipayOpenAgentCreateModel;
|
||||
import com.alipay.api.domain.ContactModel;
|
||||
import com.alipay.api.domain.SignAddressInfo;
|
||||
import com.alipay.api.request.AlipayOpenAgentConfirmRequest;
|
||||
import com.alipay.api.request.AlipayOpenAgentCreateRequest;
|
||||
import com.alipay.api.request.AlipayOpenAgentFacetofaceSignRequest;
|
||||
import com.alipay.api.request.AlipayOpenAgentOrderQueryRequest;
|
||||
import com.alipay.api.response.AlipayOpenAgentConfirmResponse;
|
||||
import com.alipay.api.response.AlipayOpenAgentCreateResponse;
|
||||
import com.alipay.api.response.AlipayOpenAgentFacetofaceSignResponse;
|
||||
import com.alipay.api.response.AlipayOpenAgentOrderQueryResponse;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.entity.MchInfo;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchApplymentService;
|
||||
import com.jeequan.jeepay.core.model.applyment.AlipayApplymentInfo;
|
||||
import com.jeequan.jeepay.core.model.applyment.ApplymentSignInfo;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvsubMchParams;
|
||||
import com.jeequan.jeepay.service.impl.MchInfoService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.thirdparty.model.AlipayClientWrapper;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* 支付宝接口进件
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/1/17 9:58
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AlipayMchApplymentService implements IIsvmchApplymentService<AlipayApplymentInfo> {
|
||||
|
||||
@Autowired private ConfigContextQueryService configContextQueryService;
|
||||
@Autowired protected SysConfigService sysConfigService;
|
||||
@Autowired protected MchInfoService mchInfoService;
|
||||
|
||||
@Override
|
||||
public MchApplyment firstApplyment(MchApplyment mchApplyment) {
|
||||
MchApplyment result = new MchApplyment();
|
||||
|
||||
// 发起商户是否为特约商户
|
||||
if (StringUtils.isEmpty(mchApplyment.getIsvNo())) {
|
||||
throw new BizException("当前商户非特约商户");
|
||||
}
|
||||
|
||||
// 查询当前商户信息
|
||||
MchInfo mchInfo = mchInfoService.getById(mchApplyment.getMchNo());
|
||||
|
||||
MchAppConfigContext context = new MchAppConfigContext();
|
||||
context.setMchInfo(mchInfo);
|
||||
context.setMchType(mchInfo.getType());
|
||||
AlipayClientWrapper alipayClientWrapper = configContextQueryService.getAlipayClientWrapper(context);
|
||||
if (alipayClientWrapper == null) {
|
||||
throw new BizException("当前服务商未配置支付宝参数");
|
||||
}
|
||||
|
||||
// 获取详细参数
|
||||
AlipayApplymentInfo info = JSON.parseObject(mchApplyment.getApplyDetailInfo(), AlipayApplymentInfo.class);
|
||||
|
||||
/* 发起进件 */
|
||||
if (AlipayApplymentInfo.PRODUCT_TYPE_OFFLINE.equals(info.getProductType())) { // 当面付
|
||||
result = toApplyOffline(info, alipayClientWrapper);
|
||||
}else {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo("尚未支持该产品");
|
||||
}
|
||||
result.setApplyDetailInfo(JSON.toJSONString(info)); //重新更新全量参数(包含imgCache)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MchApplyment rejectModify(MchApplyment mchApplyment) {
|
||||
return firstApplyment(mchApplyment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MchApplyment replenishInfo(MchApplyment mchApplyment) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MchApplyment query(MchApplyment mchApplyment) {
|
||||
|
||||
// 查询当前商户信息
|
||||
MchInfo mchInfo = mchInfoService.getById(mchApplyment.getMchNo());
|
||||
|
||||
MchAppConfigContext context = new MchAppConfigContext();
|
||||
context.setMchInfo(mchInfo);
|
||||
context.setMchType(mchInfo.getType());
|
||||
AlipayClientWrapper alipayClientWrapper = configContextQueryService.getAlipayClientWrapper(context);
|
||||
if (alipayClientWrapper == null) {
|
||||
throw new BizException("当前服务商未配置支付宝参数");
|
||||
}
|
||||
// 调用查询接口
|
||||
AlipayOpenAgentOrderQueryRequest queryRequest = new AlipayOpenAgentOrderQueryRequest();
|
||||
// 调用进件接口
|
||||
JSONObject reqJSON = new JSONObject();
|
||||
reqJSON.put("batch_no", mchApplyment.getChannelApplyNo()); // 接入方商户号+申请编号 唯一
|
||||
queryRequest.setBizContent(reqJSON.toJSONString());
|
||||
log.info("请求支付宝进件查询接口参数: req={}", reqJSON);
|
||||
AlipayOpenAgentOrderQueryResponse queryResponse = alipayClientWrapper.execute(queryRequest);
|
||||
log.info("请求支付宝查询接口 code={}, msg={}, subCode={}, subMsg={}", queryResponse.getCode(), queryResponse.getMsg(), queryResponse.getSubCode(), queryResponse.getSubMsg());
|
||||
|
||||
// 创建返回对象
|
||||
MchApplyment result = new MchApplyment();
|
||||
// 业务异常
|
||||
if(!queryResponse.isSuccess()){
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo(queryResponse.getCode() + "[" + queryResponse.getMsg() + "]" + queryResponse.getSubCode() + "[" + queryResponse.getSubMsg() + "]");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 审核状态
|
||||
if(queryResponse.isSuccess()){
|
||||
if ("MERCHANT_CONFIRM".equals(queryResponse.getOrderStatus())) { // 待商户确认
|
||||
result.setState(MchApplyment.STATE_WAIT_SIGN);
|
||||
// 放置请求ID
|
||||
result.setChannelApplyNo(queryResponse.getAgentAppId());
|
||||
// 商户签约地址
|
||||
result.setApplyErrorInfo(queryResponse.getConfirmUrl());
|
||||
}else if ("MERCHANT_CONFIRM_SUCCESS".equals(queryResponse.getOrderStatus())) { // 商户确认成功
|
||||
result.setState(MchApplyment.STATE_SUCCESS);
|
||||
|
||||
}else if ("MERCHANT_AUDITING".equals(queryResponse.getOrderStatus())) { // 审核中
|
||||
result.setState(MchApplyment.STATE_AUDITING);
|
||||
|
||||
}else { // 异常失败
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo(queryResponse.getCode() + "[" + queryResponse.getMsg() + "]" + queryResponse.getSubCode() + "[" + queryResponse.getSubMsg() + "]" + "[" + queryResponse.getRejectReason() + "]");
|
||||
}
|
||||
|
||||
// 封装支付参数
|
||||
AlipayIsvsubMchParams mchParams = new AlipayIsvsubMchParams();
|
||||
mchParams.setAppAuthToken(queryResponse.getMerchantPid());
|
||||
result.setSuccResParameter(JSON.toJSONString(mchParams));
|
||||
return result;
|
||||
}else{
|
||||
|
||||
// 审核中
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
return result;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplymentSignInfo signInfo(MchApplyment mchApplyment) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private MchApplyment toApplyOffline(AlipayApplymentInfo info, AlipayClientWrapper alipayClientWrapper) {
|
||||
// 创建返回对象
|
||||
MchApplyment result = new MchApplyment();
|
||||
String batchNo = "";
|
||||
try {
|
||||
/* 1.开启事务 */
|
||||
AlipayOpenAgentCreateRequest openRequest = new AlipayOpenAgentCreateRequest();
|
||||
AlipayOpenAgentCreateModel openModel = new AlipayOpenAgentCreateModel();
|
||||
|
||||
ContactModel contactModel = new ContactModel();
|
||||
contactModel.setContactName(info.getContactName()); // 联系人名称
|
||||
contactModel.setContactMobile(info.getContactPhone()); // 联系人手机号码
|
||||
contactModel.setContactEmail(info.getContactEmail()); // 联系人邮箱
|
||||
openModel.setContactInfo(contactModel);
|
||||
|
||||
openModel.setAccount(info.getAccountNo());
|
||||
openRequest.setBizModel(openModel);
|
||||
|
||||
AlipayOpenAgentCreateResponse response = alipayClientWrapper.execute(openRequest);
|
||||
log.info("【1】开启代商户签约,开启事务:code={}, msg={}", response.getCode(), response.getMsg());
|
||||
|
||||
if (!response.isSuccess()) {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo(response.getCode() + "[" + response.getMsg() + "]" + response.getSubCode() + "[" + response.getSubMsg() + "]");
|
||||
log.error("支付宝【当面付】进件开启事务失败;msg={}, subMsg={}", response.getMsg(), response.getSubMsg());
|
||||
return result;
|
||||
}
|
||||
if (!"init".equals(response.getBatchStatus())) {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo(response.getCode() + "[" + response.getMsg() + "]" + response.getSubCode() + "[" + response.getSubMsg() + "]");
|
||||
log.error("支付宝【当面付】进件batchStatus状态不等于init,提交事务失败");
|
||||
return result;
|
||||
}
|
||||
batchNo = response.getBatchNo();
|
||||
|
||||
// 放置请求ID
|
||||
result.setChannelApplyNo(batchNo);
|
||||
/* 2.发起待签约 */
|
||||
AlipayOpenAgentFacetofaceSignRequest offRequest = new AlipayOpenAgentFacetofaceSignRequest();
|
||||
|
||||
offRequest.setBatchNo(batchNo); // 代商户操作事务编号
|
||||
|
||||
offRequest.setMccCode(info.getMccCode()); // 所属经营类目编码
|
||||
|
||||
// 特殊资质证书
|
||||
if (StringUtils.isNotEmpty(info.getSpecialLicenseImg())) {
|
||||
//下载文件 & 转换为byte数组格式
|
||||
byte[] imgFileByteArray = IOUtils.toByteArray(new URL(info.getSpecialLicenseImg()));
|
||||
offRequest.setSpecialLicensePic(new FileItem("1.png", imgFileByteArray));
|
||||
}
|
||||
|
||||
// 服务费率
|
||||
offRequest.setRate(info.convertPaywayFeeList2String());
|
||||
|
||||
// 营业执照编号
|
||||
offRequest.setBusinessLicenseNo(info.getLicenseNo());
|
||||
|
||||
// 营业执照照片
|
||||
if (StringUtils.isNotEmpty(info.getLicenseImg())) {
|
||||
//下载文件 & 转换为byte数组格式
|
||||
byte[] imgFileByteArray = IOUtils.toByteArray(new URL(info.getLicenseImg()));
|
||||
offRequest.setBusinessLicensePic(new FileItem("1.png", imgFileByteArray));
|
||||
}
|
||||
// 营业期限
|
||||
if (StringUtils.isNotEmpty(info.getLicenseEffectEnd())) {
|
||||
if ("长期".equals(info.getLicenseEffectEnd())) {
|
||||
offRequest.setLongTerm(true);
|
||||
}else {
|
||||
offRequest.setDateLimitation(info.getLicenseEffectEnd());
|
||||
}
|
||||
}
|
||||
// 店铺门头照
|
||||
if (StringUtils.isNotEmpty(info.getStoreOuterImg())) {
|
||||
//下载文件 & 转换为byte数组格式
|
||||
byte[] imgFileByteArray = IOUtils.toByteArray(new URL(info.getStoreOuterImg()));
|
||||
offRequest.setShopSignBoardPic(new FileItem("1.png", imgFileByteArray));
|
||||
}
|
||||
// 门店名称
|
||||
offRequest.setShopName(info.getMchFullName());
|
||||
|
||||
// 店铺内景照
|
||||
if (StringUtils.isNotEmpty(info.getStoreInnerImg())) {
|
||||
//下载文件 & 转换为byte数组格式
|
||||
byte[] imgFileByteArray = IOUtils.toByteArray(new URL(info.getStoreInnerImg()));
|
||||
offRequest.setShopScenePic(new FileItem("1.png", imgFileByteArray));
|
||||
}
|
||||
|
||||
// 营业执照法人手机号
|
||||
offRequest.setBusinessLicenseMobile(info.getContactPhone());
|
||||
|
||||
// 店铺地址
|
||||
SignAddressInfo addressInfo = new SignAddressInfo();
|
||||
addressInfo.setCountryCode("156");
|
||||
addressInfo.setProvinceCode(info.getAreaCode().getString(0)); // 省编码
|
||||
addressInfo.setCityCode(info.getAreaCode().getString(1)); // 市编码
|
||||
addressInfo.setDistrictCode(info.getAreaCode().getString(2)); // 区编码
|
||||
addressInfo.setDetailAddress(info.getAddress()); // 详细地址
|
||||
offRequest.setShopAddress(addressInfo);
|
||||
|
||||
AlipayOpenAgentFacetofaceSignResponse signResponse = alipayClientWrapper.execute(offRequest);
|
||||
log.info("【2】待签约当面付:code={}, msg={}, subCode={}, subMsg={}", signResponse.getCode(), signResponse.getMsg(), signResponse.getSubCode(), signResponse.getSubMsg());
|
||||
if (!signResponse.isSuccess()) {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo(signResponse.getCode() + "[" + signResponse.getMsg() + "]" + signResponse.getSubCode() + "[" + signResponse.getSubMsg() + "]");
|
||||
log.error("发起待签约失败:code={}, msg={}, subCode={}, subMsg={}", signResponse.getCode(), signResponse.getMsg(), signResponse.getSubCode(), signResponse.getSubMsg());
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 3.提交待签约事务 */
|
||||
AlipayOpenAgentConfirmRequest confirmRequest = new AlipayOpenAgentConfirmRequest();
|
||||
AlipayOpenAgentConfirmModel confirmModel = new AlipayOpenAgentConfirmModel();
|
||||
confirmModel.setBatchNo(batchNo);
|
||||
confirmRequest.setBizModel(confirmModel);
|
||||
AlipayOpenAgentConfirmResponse confirmResponse = alipayClientWrapper.execute(confirmRequest);
|
||||
log.info("【3】提交待签约事务:code={}, msg={}, subCode={}, subMsg={}", confirmResponse.getCode(), confirmResponse.getMsg(), confirmResponse.getSubCode(), confirmResponse.getSubMsg());
|
||||
if (!confirmResponse.isSuccess()) {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY); // 失败
|
||||
result.setApplyErrorInfo(confirmResponse.getCode() + "[" + confirmResponse.getMsg() + "]" + confirmResponse.getSubCode() + "[" + confirmResponse.getSubMsg() + "]");
|
||||
log.error("提交待签约事务失败:code={}, msg={}, subCode={}, subMsg={}", confirmResponse.getCode(), confirmResponse.getMsg(), confirmResponse.getSubCode(), confirmResponse.getSubMsg());
|
||||
return result;
|
||||
}
|
||||
result.setState(MchApplyment.STATE_AUDITING); // 审核中
|
||||
}catch (Exception e) {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo("[" + e.getMessage() + "]");
|
||||
log.error("进件异常:{}", e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alipay.api.domain.AlipayOpenAuthTokenAppModel;
|
||||
import com.alipay.api.request.AlipayOpenAuthTokenAppRequest;
|
||||
import com.alipay.api.response.AlipayOpenAuthTokenAppResponse;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IMchAutoAuthService;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.thirdparty.model.AlipayClientWrapper;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 支付宝: 商户授权实现类
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:21
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AlipayMchAutoAuthService implements IMchAutoAuthService {
|
||||
|
||||
@Autowired private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
|
||||
@Override
|
||||
public JSONObject mchAuth(MchAppConfigContext mchAppConfigContext, String appAuthCode) {
|
||||
|
||||
AlipayClientWrapper alipayClientWrapper = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext);
|
||||
|
||||
AlipayOpenAuthTokenAppRequest request = new AlipayOpenAuthTokenAppRequest();
|
||||
AlipayOpenAuthTokenAppModel model = new AlipayOpenAuthTokenAppModel();
|
||||
model.setGrantType("authorization_code");
|
||||
model.setCode(appAuthCode);
|
||||
request.setBizModel(model);
|
||||
|
||||
// expiresIn: 该字段已作废,应用令牌长期有效,接入方不需要消费该字段
|
||||
// reExpiresIn: 刷新令牌的有效时间(从接口调用时间作为起始时间),单位到秒
|
||||
// DateUtil.offsetSecond(new Date(), Integer.parseInt(resp.getExpiresIn()));
|
||||
AlipayOpenAuthTokenAppResponse resp = alipayClientWrapper.execute(request);
|
||||
if(!resp.isSuccess()){
|
||||
throw new BizException(AlipayKit.appendErrMsg(resp.getMsg(), resp.getSubMsg()));
|
||||
}
|
||||
|
||||
return (JSONObject) JSON.toJSON(resp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alipay.api.domain.AlipayOpenSpOperationApplyModel;
|
||||
import com.alipay.api.domain.AlipayOpenSpOperationQrcodeQueryModel;
|
||||
import com.alipay.api.domain.AlipayOpenSpOperationResultQueryModel;
|
||||
import com.alipay.api.request.AlipayOpenSpOperationApplyRequest;
|
||||
import com.alipay.api.request.AlipayOpenSpOperationQrcodeQueryRequest;
|
||||
import com.alipay.api.request.AlipayOpenSpOperationResultQueryRequest;
|
||||
import com.alipay.api.response.AlipayOpenSpOperationApplyResponse;
|
||||
import com.alipay.api.response.AlipayOpenSpOperationQrcodeQueryResponse;
|
||||
import com.alipay.api.response.AlipayOpenSpOperationResultQueryResponse;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.alipaybiz.IAlipayOpenSpOperationService;
|
||||
import com.jeequan.jeepay.core.model.alipay.AlipaySpOperationInfo;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvParams;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 支付宝服务商代运营授权
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2023/3/8 15:13
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AlipayOpenSpOperationService implements IAlipayOpenSpOperationService {
|
||||
|
||||
@Override
|
||||
public JSONObject querySpOperationQrcode(AlipayIsvParams alipayIsvParams, String alipayAccount) {
|
||||
AlipayOpenSpOperationQrcodeQueryRequest request = new AlipayOpenSpOperationQrcodeQueryRequest();
|
||||
AlipayOpenSpOperationQrcodeQueryModel model = new AlipayOpenSpOperationQrcodeQueryModel();
|
||||
model.setOutBizNo(IdUtil.fastSimpleUUID()); // 外部操作流水,由服务商自定义,需确保每次操作唯一
|
||||
model.setOperateType("OPERATION_AUTH"); // OPERATION_AUTH:代运营授权,支持间连、直连商户。ACCOUNT_BIND:账号绑定,仅支持间连商户。
|
||||
model.setAlipayAccount(alipayAccount);
|
||||
model.setAccessProductCode("OPENAPI_AUTH_DEFAULT");
|
||||
request.setBizModel(model);
|
||||
|
||||
AlipayOpenSpOperationQrcodeQueryResponse response = AlipayKit.getAlipayClientWrapper(alipayIsvParams).getAlipayClient().execute(request);
|
||||
if (!response.isSuccess()) {
|
||||
throw new BizException(AlipayKit.appendErrMsg(response.getMsg(), response.getSubMsg()));
|
||||
}
|
||||
|
||||
return (JSONObject) JSON.toJSON(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject applySpOperation(AlipayIsvParams alipayIsvParams, String alipayAccount){
|
||||
AlipayOpenSpOperationApplyRequest request = new AlipayOpenSpOperationApplyRequest();
|
||||
AlipayOpenSpOperationApplyModel model = new AlipayOpenSpOperationApplyModel();
|
||||
model.setOutBizNo(IdUtil.fastSimpleUUID());
|
||||
model.setOperateType("OPERATION_AUTH");
|
||||
model.setAlipayAccount(alipayAccount);
|
||||
model.setAccessProductCode("OPENAPI_AUTH_DEFAULT");
|
||||
request.setBizModel(model);
|
||||
|
||||
AlipayOpenSpOperationApplyResponse response = AlipayKit.getAlipayClientWrapper(alipayIsvParams).getAlipayClient().execute(request);
|
||||
if (!response.isSuccess()) {
|
||||
throw new BizException(AlipayKit.appendErrMsg(response.getMsg(), response.getSubMsg()));
|
||||
}
|
||||
|
||||
return (JSONObject) JSON.toJSON(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlipaySpOperationInfo querySpOperationResult(AlipayIsvParams alipayIsvParams, String alipayAccount){
|
||||
AlipayOpenSpOperationResultQueryRequest request = new AlipayOpenSpOperationResultQueryRequest();
|
||||
AlipayOpenSpOperationResultQueryModel model = new AlipayOpenSpOperationResultQueryModel();
|
||||
model.setOperateType("OPERATION_AUTH");
|
||||
model.setAlipayAccount(alipayAccount);
|
||||
model.setAccessProductCode("OPENAPI_AUTH_DEFAULT");
|
||||
request.setBizModel(model);
|
||||
|
||||
AlipayOpenSpOperationResultQueryResponse response = AlipayKit.getAlipayClientWrapper(alipayIsvParams).getAlipayClient().execute(request);
|
||||
|
||||
AlipaySpOperationInfo operationInfo = new AlipaySpOperationInfo();
|
||||
BeanUtil.copyProperties(response, operationInfo);
|
||||
|
||||
return operationInfo;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import com.alipay.api.domain.AlipayTradeCloseModel;
|
||||
import com.alipay.api.request.AlipayTradeCloseRequest;
|
||||
import com.alipay.api.response.AlipayTradeCloseResponse;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IPayOrderCloseService;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 支付宝 关闭订单接口实现类
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/1/25 11:17
|
||||
*/
|
||||
@Service
|
||||
public class AlipayPayOrderCloseService implements IPayOrderCloseService {
|
||||
|
||||
@Autowired private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg close(PayOrder payOrder, MchAppConfigContext mchAppConfigContext){
|
||||
|
||||
AlipayTradeCloseRequest req = new AlipayTradeCloseRequest();
|
||||
|
||||
// 商户订单号,商户网站订单系统中唯一订单号,必填
|
||||
AlipayTradeCloseModel model = new AlipayTradeCloseModel();
|
||||
model.setOutTradeNo(payOrder.getPayOrderId());
|
||||
req.setBizModel(model);
|
||||
|
||||
//通用字段
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, req, model);
|
||||
|
||||
AlipayTradeCloseResponse resp = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).execute(req);
|
||||
|
||||
// 返回状态成功
|
||||
if (resp.isSuccess()) {
|
||||
return ChannelRetMsg.confirmSuccess(resp.getTradeNo());
|
||||
}else {
|
||||
return ChannelRetMsg.sysError(resp.getSubMsg());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import com.alipay.api.domain.AlipayTradeQueryModel;
|
||||
import com.alipay.api.request.AlipayTradeQueryRequest;
|
||||
import com.alipay.api.response.AlipayTradeQueryResponse;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IPayOrderQueryService;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 支付宝 查单接口实现类
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:20
|
||||
*/
|
||||
@Service
|
||||
public class AlipayPayOrderQueryService implements IPayOrderQueryService {
|
||||
|
||||
@Autowired private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg query(PayOrder payOrder, MchAppConfigContext mchAppConfigContext){
|
||||
|
||||
AlipayTradeQueryRequest req = new AlipayTradeQueryRequest();
|
||||
|
||||
// 商户订单号,商户网站订单系统中唯一订单号,必填
|
||||
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
|
||||
model.setOutTradeNo(payOrder.getPayOrderId());
|
||||
req.setBizModel(model);
|
||||
|
||||
//通用字段
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, req, model);
|
||||
|
||||
AlipayTradeQueryResponse resp = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).execute(req);
|
||||
String result = resp.getTradeStatus();
|
||||
|
||||
if("TRADE_SUCCESS".equals(result)) {
|
||||
return ChannelRetMsg.confirmSuccess(resp.getTradeNo(), resp.getTradeNo(), payOrder.getPayOrderId(),null); //支付成功
|
||||
}else if("WAIT_BUYER_PAY".equals(result)) {
|
||||
return ChannelRetMsg.waiting(); //支付中
|
||||
}
|
||||
return ChannelRetMsg.waiting(); //支付中
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.PaywayUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 支付接口: 支付宝官方
|
||||
* 支付方式: 自适应
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:19
|
||||
*/
|
||||
@Service
|
||||
public class AlipayPaymentService extends AbstractPaymentService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.ALIPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupport(String wayCode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
return PaywayUtil.getRealPaywayService(this, payOrder.getWayCode()).preCheck(rq, payOrder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
return PaywayUtil.getRealPaywayService(this, payOrder.getWayCode()).pay(rq, payOrder, mchAppConfigContext);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
|
||||
import com.alipay.api.domain.AlipayTradeRefundModel;
|
||||
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
|
||||
import com.alipay.api.request.AlipayTradeRefundRequest;
|
||||
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
|
||||
import com.alipay.api.response.AlipayTradeRefundResponse;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.entity.RefundOrder;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRefundLimit;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.refund.RefundOrderRQ;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractRefundService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 退款接口: 支付宝官方
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/17 9:38
|
||||
*/
|
||||
@Service
|
||||
public class AlipayRefundService extends AbstractRefundService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.ALIPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String preCheck(RefundOrderRQ bizRQ, RefundOrder refundOrder, PayOrder payOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg refund(RefundOrderRQ bizRQ, RefundOrder refundOrder, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
|
||||
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
|
||||
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
|
||||
model.setOutTradeNo(refundOrder.getPayOrderId());
|
||||
model.setTradeNo(refundOrder.getChannelPayOrderNo());
|
||||
model.setOutRequestNo(refundOrder.getRefundOrderId());
|
||||
model.setRefundAmount(AmountUtil.convertCent2Dollar(refundOrder.getRefundAmount().toString()));
|
||||
model.setRefundReason(refundOrder.getRefundReason());
|
||||
request.setBizModel(model);
|
||||
|
||||
//统一放置 isv接口必传信息
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, request, model);
|
||||
|
||||
AlipayTradeRefundResponse response = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).execute(request);
|
||||
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
channelRetMsg.setChannelAttach(response.getBody());
|
||||
|
||||
// 调用成功
|
||||
if(response.isSuccess()){
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
}else{
|
||||
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
channelRetMsg.setChannelErrCode(response.getSubCode());
|
||||
channelRetMsg.setChannelErrMsg(response.getSubMsg());
|
||||
}
|
||||
return channelRetMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg query(RefundOrder refundOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
|
||||
AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
|
||||
AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
|
||||
model.setTradeNo(refundOrder.getChannelPayOrderNo());
|
||||
model.setOutTradeNo(refundOrder.getPayOrderId());
|
||||
model.setOutRequestNo(refundOrder.getRefundOrderId());
|
||||
request.setBizModel(model);
|
||||
|
||||
//统一放置 isv接口必传信息
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, request, model);
|
||||
|
||||
AlipayTradeFastpayRefundQueryResponse response = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).execute(request);
|
||||
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
channelRetMsg.setChannelAttach(response.getBody());
|
||||
|
||||
// 调用成功 & 金额相等 (传入不存在的outRequestNo支付宝仍然返回响应成功只是数据不存在, 调用isSuccess() 仍是成功, 此处需判断金额是否相等)
|
||||
Long channelRefundAmount = response.getRefundAmount() == null ? null : Long.parseLong(AmountUtil.convertDollar2Cent(response.getRefundAmount()));
|
||||
if(response.isSuccess() && refundOrder.getRefundAmount().equals(channelRefundAmount)){
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
}else{
|
||||
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING); //认为是处理中
|
||||
|
||||
}
|
||||
|
||||
return channelRetMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPlatAccount(RefundOrder refundOrder) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款权限
|
||||
* @param settleType
|
||||
* @param applyId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChannelRefundLimit isRefundLimit(String settleType,String applyId) {
|
||||
return super.isRefundLimit(settleType,applyId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alipay.api.domain.*;
|
||||
import com.alipay.api.request.*;
|
||||
import com.alipay.api.response.*;
|
||||
import com.jeequan.jeepay.core.entity.MchStore;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.alipaybiz.IAlipayShopService;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvParams;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 蚂蚁店铺管理接口
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2023/3/8 15:13
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AlipayShopService implements IAlipayShopService {
|
||||
|
||||
@Override
|
||||
public MchStore query(AlipayIsvParams alipayIsvParams, String storeId, String ipRoleId) {
|
||||
AntMerchantExpandShopQueryRequest request = new AntMerchantExpandShopQueryRequest();
|
||||
AntMerchantExpandShopQueryModel model = new AntMerchantExpandShopQueryModel();
|
||||
|
||||
model.setStoreId(storeId); // 系统门店ID
|
||||
model.setIpRoleId(ipRoleId); // 直连开店场景,填写商户pid
|
||||
request.setBizModel(model);
|
||||
|
||||
AntMerchantExpandShopQueryResponse response = AlipayKit.getAlipayClientWrapper(alipayIsvParams).getAlipayClient().execute(request);
|
||||
if (!response.isSuccess()) {
|
||||
throw new BizException(AlipayKit.appendErrMsg(response.getMsg(), response.getSubMsg()));
|
||||
}
|
||||
|
||||
// 转换为商户门店信息
|
||||
MchStore mchStore = new MchStore();
|
||||
mchStore.setAlipayShopId(response.getShopId());
|
||||
mchStore.setStoreName(response.getShopName());
|
||||
mchStore.setContactPhone(response.getContactMobile());
|
||||
mchStore.addExt("shopCategory", response.getNewShopCategory());
|
||||
mchStore.addExt("shopType", response.getShopType());
|
||||
|
||||
AddressInfo businessAddress = response.getBusinessAddress();
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
jsonArray.add(businessAddress.getProvinceCode());
|
||||
jsonArray.add(businessAddress.getCityCode());
|
||||
jsonArray.add(businessAddress.getDistrictCode());
|
||||
mchStore.setAreaCode(jsonArray);
|
||||
mchStore.setAddress(businessAddress.getAddress());
|
||||
mchStore.setLat(businessAddress.getLatitude());
|
||||
mchStore.setLng(businessAddress.getLongitude());
|
||||
|
||||
return mchStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MchStore create(AlipayIsvParams alipayIsvParams, MchStore mchStore, String ipRoleId){
|
||||
AntMerchantExpandShopCreateRequest request = new AntMerchantExpandShopCreateRequest();
|
||||
AntMerchantExpandShopCreateModel model = new AntMerchantExpandShopCreateModel();
|
||||
|
||||
// 经营地址
|
||||
AddressInfo businessAddress = new AddressInfo();
|
||||
businessAddress.setProvinceCode(mchStore.getAreaCode().getString(0));
|
||||
businessAddress.setCityCode(mchStore.getAreaCode().getString(1));
|
||||
businessAddress.setDistrictCode(mchStore.getAreaCode().getString(2));
|
||||
businessAddress.setAddress(mchStore.getAddress());
|
||||
model.setBusinessAddress(businessAddress);
|
||||
|
||||
if (mchStore.getExt() != null) {
|
||||
if (StringUtils.isNotBlank(mchStore.getExt().getString("shopCategory"))) {
|
||||
model.setShopCategory(mchStore.getExt().getString("shopCategory").split("_")[1]); // 新版门店类目标准二级类目code
|
||||
}
|
||||
model.setShopType(mchStore.getExt().getString("shopType")); // 店铺经营类型,01表示直营,02表示加盟
|
||||
}
|
||||
|
||||
model.setStoreId(mchStore.getStoreId() + ""); // 外部门店ID
|
||||
model.setIpRoleId(ipRoleId);
|
||||
model.setShopName(mchStore.getStoreName());
|
||||
model.setContactMobile(mchStore.getContactPhone());
|
||||
request.setBizModel(model);
|
||||
|
||||
AntMerchantExpandShopCreateResponse response = AlipayKit.getAlipayClientWrapper(alipayIsvParams).getAlipayClient().execute(request);
|
||||
log.info("蚂蚁店铺创建响应,storeId={},response={}", mchStore.getStoreId(), JSONObject.toJSONString(response));
|
||||
if (!response.isSuccess()) {
|
||||
throw new BizException(AlipayKit.appendErrMsg(response.getMsg(), response.getSubMsg()));
|
||||
}
|
||||
|
||||
MchStore result = new MchStore();
|
||||
result.setAlipayShopCreateId(response.getOrderId());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MchStore update(AlipayIsvParams alipayIsvParams, MchStore mchStore){
|
||||
AntMerchantExpandShopModifyRequest request = new AntMerchantExpandShopModifyRequest();
|
||||
AntMerchantExpandShopModifyModel model = new AntMerchantExpandShopModifyModel();
|
||||
|
||||
model.setShopId(mchStore.getAlipayShopId());
|
||||
|
||||
// 经营地址
|
||||
AddressInfo businessAddress = new AddressInfo();
|
||||
businessAddress.setProvinceCode(mchStore.getAreaCode().getString(0));
|
||||
businessAddress.setCityCode(mchStore.getAreaCode().getString(1));
|
||||
businessAddress.setDistrictCode(mchStore.getAreaCode().getString(2));
|
||||
businessAddress.setAddress(mchStore.getAddress());
|
||||
model.setBusinessAddress(businessAddress);
|
||||
|
||||
if (mchStore.getExt() != null) {
|
||||
if (StringUtils.isNotBlank(mchStore.getExt().getString("shopCategory")) && mchStore.getExt().getString("shopCategory").contains("_")) {
|
||||
model.setShopCategory(mchStore.getExt().getString("shopCategory").split("_")[1]); // 新版门店类目标准二级类目code
|
||||
}else {
|
||||
model.setShopCategory(mchStore.getExt().getString("shopCategory")); // 新版门店类目标准二级类目code
|
||||
}
|
||||
}
|
||||
|
||||
model.setShopName(mchStore.getStoreName());
|
||||
model.setContactMobile(mchStore.getContactPhone());
|
||||
request.setBizModel(model);
|
||||
|
||||
AntMerchantExpandShopModifyResponse response = AlipayKit.getAlipayClientWrapper(alipayIsvParams).getAlipayClient().execute(request);
|
||||
log.info("蚂蚁店铺修改响应,storeId={},response={}", mchStore.getStoreId(), JSONObject.toJSONString(response));
|
||||
if (!response.isSuccess()) {
|
||||
throw new BizException(AlipayKit.appendErrMsg(response.getMsg(), response.getSubMsg()));
|
||||
}
|
||||
|
||||
MchStore result = new MchStore();
|
||||
result.setAlipayShopCreateId(response.getOrderId());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(AlipayIsvParams alipayIsvParams, String alipayShopId) {
|
||||
AntMerchantExpandShopCloseRequest request = new AntMerchantExpandShopCloseRequest();
|
||||
AntMerchantExpandShopCloseModel model = new AntMerchantExpandShopCloseModel();
|
||||
model.setShopId(alipayShopId);
|
||||
|
||||
request.setBizModel(model);
|
||||
|
||||
AntMerchantExpandShopCloseResponse response = AlipayKit.getAlipayClientWrapper(alipayIsvParams).getAlipayClient().execute(request);
|
||||
if (!response.isSuccess()) {
|
||||
throw new BizException(AlipayKit.appendErrMsg(response.getMsg(), response.getSubMsg()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MchStore createResultQuery(AlipayIsvParams alipayIsvParams, String orderId){
|
||||
AntMerchantExpandOrderQueryRequest request = new AntMerchantExpandOrderQueryRequest();
|
||||
AntMerchantExpandOrderQueryModel model = new AntMerchantExpandOrderQueryModel();
|
||||
model.setOrderId(orderId);
|
||||
request.setBizModel(model);
|
||||
|
||||
AntMerchantExpandOrderQueryResponse response = AlipayKit.getAlipayClientWrapper(alipayIsvParams).getAlipayClient().execute(request);
|
||||
log.info("蚂蚁店铺申请单查询接口响应,orderId={},response={}", orderId, JSONObject.toJSONString(response));
|
||||
if (!response.isSuccess()) {
|
||||
throw new BizException(AlipayKit.appendErrMsg(response.getMsg(), response.getSubMsg()));
|
||||
}
|
||||
|
||||
MchStore result = new MchStore();
|
||||
if (StringUtils.isNotBlank(response.getExtInfo())) {
|
||||
JSONObject extInfo = JSONObject.parseObject(response.getExtInfo());
|
||||
result.setAlipayShopId(extInfo.getString("SHOP_ID"));
|
||||
}
|
||||
result.setAlipayShopStatus(response.getStatus());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alipay.api.internal.util.AlipaySignature;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.TransferOrder;
|
||||
import com.jeequan.jeepay.core.exception.ResponseException;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayConfig;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractTransferNoticeService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
/*
|
||||
* 支付宝 转账回调接口实现类
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2021/21/01 17:16
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class AlipayTransferNoticeService extends AbstractTransferNoticeService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.ALIPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlOrderId) {
|
||||
|
||||
try {
|
||||
|
||||
JSONObject params = getReqParamJSON();
|
||||
log.info("【支付宝转账】回调通知参数:{}", params.toJSONString());
|
||||
|
||||
JSONObject bizContent = JSONObject.parseObject(params.getString("biz_content"));
|
||||
|
||||
String transferId = bizContent.getString("out_biz_no");
|
||||
return MutablePair.of(transferId, params);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("error", e);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg doNotice(HttpServletRequest request, Object params, TransferOrder transferOrder) {
|
||||
|
||||
String logPrefix = "【支付宝转账通知】";
|
||||
|
||||
try {
|
||||
//配置参数获取
|
||||
Byte useCert = null;
|
||||
String alipaySignType, alipayPublicCert, alipayPublicKey;
|
||||
// 获取支付参数
|
||||
AlipayIsvParams alipayParams = (AlipayIsvParams) configContextQueryService.queryTransferIsvParams(transferOrder.getIsvNo(), getIfCode());
|
||||
|
||||
useCert = alipayParams.getUseCert();
|
||||
alipaySignType = alipayParams.getSignType();
|
||||
alipayPublicCert = alipayParams.getAlipayPublicCert();
|
||||
alipayPublicKey = alipayParams.getAlipayPublicKey();
|
||||
// 获取请求参数
|
||||
JSONObject jsonParams = (JSONObject) params;
|
||||
JSONObject bizContent = JSONObject.parseObject(jsonParams.getString("biz_content"));
|
||||
|
||||
boolean verifyResult;
|
||||
if(useCert != null && useCert == CS.YES){ //证书方式
|
||||
|
||||
verifyResult = AlipaySignature.rsaCertCheckV1(jsonParams.toJavaObject(Map.class), getCertFilePath(alipayPublicCert),
|
||||
AlipayConfig.CHARSET, alipaySignType);
|
||||
|
||||
}else{
|
||||
verifyResult = AlipaySignature.rsaCheckV1(jsonParams.toJavaObject(Map.class), alipayPublicKey, AlipayConfig.CHARSET, alipaySignType);
|
||||
}
|
||||
|
||||
//验签失败
|
||||
if(!verifyResult){
|
||||
log.error("{},验签失败", logPrefix);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
|
||||
//验签成功后判断上游订单状态
|
||||
ResponseEntity okResponse = textResp("SUCCESS");
|
||||
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
channelRetMsg.setResponseEntity(okResponse); // 响应数据
|
||||
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING); // 默认转账中
|
||||
|
||||
// 成功-SUCCESS
|
||||
String status = bizContent.getString("status");
|
||||
if("SUCCESS".equals(status)){
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
}
|
||||
|
||||
return channelRetMsg;
|
||||
} catch (Exception e) {
|
||||
log.error("error", e);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay;
|
||||
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.domain.AlipayFundTransCommonQueryModel;
|
||||
import com.alipay.api.domain.AlipayFundTransUniTransferModel;
|
||||
import com.alipay.api.domain.ExtendParams;
|
||||
import com.alipay.api.domain.Participant;
|
||||
import com.alipay.api.request.AlipayFundTransCommonQueryRequest;
|
||||
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
|
||||
import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
|
||||
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.TransferOrder;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.alipay.AlipayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.transfer.TransferOrderRQ;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.db.entity.TransferSubjectEntity;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractTransferService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 转账接口: 支付宝官方
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/8/11 14:05
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AlipayTransferService extends AbstractTransferService {
|
||||
|
||||
@Autowired private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.ALIPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupport(String entryType) {
|
||||
|
||||
// 支付宝账户
|
||||
if(TransferOrder.ENTRY_ALIPAY_CASH.equals(entryType)){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String preCheck(TransferOrderRQ bizRQ, TransferOrder transferOrder) {
|
||||
super.preCheck(bizRQ, transferOrder);
|
||||
|
||||
/*
|
||||
* 支付宝新版转账接口:不支持服务商模式 ( 不存在 app_auth_token 参数了 )
|
||||
* 旧版文档地址: https://opendocs.alipay.com/open/309/alipay.fund.trans.toaccount.transfer
|
||||
* 新版文档地址: https://opendocs.alipay.com/open/02byuo?ref=api&scene=ca56bca529e64125a2786703c6192d41
|
||||
*/
|
||||
if(transferOrder.getMchType() == CS.MCH_TYPE_ISVSUB){
|
||||
return "支付宝子商户暂不支持转账业务";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg transfer(TransferOrderRQ bizRQ, TransferOrder transferOrder){
|
||||
|
||||
AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
|
||||
AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
|
||||
model.setTransAmount(AmountUtil.convertCent2Dollar(transferOrder.getAmount())); //转账金额,单位:元。
|
||||
model.setOutBizNo(transferOrder.getTransferId()); //商户转账唯一订单号
|
||||
model.setRemark(transferOrder.getTransferDesc()); //转账备注
|
||||
model.setProductCode("TRANS_ACCOUNT_NO_PWD"); // 销售产品码。单笔无密转账固定为 TRANS_ACCOUNT_NO_PWD
|
||||
model.setBizScene("DIRECT_TRANSFER"); // 业务场景 单笔无密转账固定为 DIRECT_TRANSFER。
|
||||
model.setOrderTitle("转账"); // 转账业务的标题,用于在支付宝用户的账单里显示。
|
||||
model.setBusinessParams(transferOrder.getChannelExtra()); // 转账业务请求的扩展参数 {\"payer_show_name_use_alias\":\"xx公司\"}
|
||||
|
||||
Participant accPayeeInfo = new Participant();
|
||||
accPayeeInfo.setName(StringUtils.defaultString(transferOrder.getAccountName(), null)); //收款方真实姓名
|
||||
accPayeeInfo.setIdentityType("ALIPAY_LOGON_ID"); //ALIPAY_USERID: 支付宝用户ID ALIPAY_LOGONID:支付宝登录账号
|
||||
accPayeeInfo.setIdentity(transferOrder.getAccountNo()); //收款方账户
|
||||
model.setPayeeInfo(accPayeeInfo);
|
||||
|
||||
request.setBizModel(model);
|
||||
|
||||
TransferSubjectEntity transferSubjectFq = transferSubjectService.getById(transferOrder.getTransferSubjectIdFq());
|
||||
|
||||
//统一放置 isv接口必传信息
|
||||
// 获取支付参数
|
||||
AlipayIsvParams isvParams = (AlipayIsvParams) configContextQueryService.queryTransferIsvParams(transferSubjectFq);
|
||||
|
||||
// 服务商信息
|
||||
ExtendParams extendParams = new ExtendParams();
|
||||
extendParams.setSysServiceProviderId(isvParams.getPid());
|
||||
|
||||
// if(model instanceof AlipayTradePayModel) {
|
||||
// ((AlipayTradePayModel)model).setExtendParams(extendParams);
|
||||
// } else if(model instanceof AlipayTradeAppPayModel) {
|
||||
// ((AlipayTradeAppPayModel)model).setExtendParams(extendParams);
|
||||
// } else if(model instanceof AlipayTradeCreateModel) {
|
||||
// ((AlipayTradeCreateModel)model).setExtendParams(extendParams);
|
||||
// } else if(model instanceof AlipayTradePagePayModel) {
|
||||
// ((AlipayTradePagePayModel)model).setExtendParams(extendParams);
|
||||
// } else if(model instanceof AlipayTradePrecreateModel) {
|
||||
// ((AlipayTradePrecreateModel)model).setExtendParams(extendParams);
|
||||
// } else if(model instanceof AlipayTradeWapPayModel) {
|
||||
// ((AlipayTradeWapPayModel)model).setExtendParams(extendParams);
|
||||
// }
|
||||
|
||||
request.putOtherTextParam("app_auth_token", isvParams.getAppAuthToken());
|
||||
|
||||
// 调起支付宝接口
|
||||
AlipayFundTransUniTransferResponse response;
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
try {
|
||||
DefaultAlipayClient alipayClient = new DefaultAlipayClient(isvParams.getConfig());
|
||||
response = alipayClient.certificateExecute(request);
|
||||
channelRetMsg.setChannelAttach(response.getBody());
|
||||
|
||||
// 调用成功
|
||||
if(response.isSuccess()){
|
||||
if ("SUCCESS".equals(response.getStatus())) {
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
channelRetMsg.setChannelOrderId(response.getOrderId());
|
||||
return channelRetMsg;
|
||||
}else if ("FAIL".equals(response.getStatus())) {
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
channelRetMsg.setChannelErrCode(AlipayKit.appendErrCode(response.getCode(), response.getSubCode()));
|
||||
channelRetMsg.setChannelErrMsg(AlipayKit.appendErrMsg(response.getMsg(), response.getSubMsg()));
|
||||
return channelRetMsg;
|
||||
}else {
|
||||
return ChannelRetMsg.waiting();
|
||||
}
|
||||
}else{
|
||||
//若 系统繁忙, 无法确认结果
|
||||
if("SYSTEM_ERROR".equalsIgnoreCase(response.getSubCode())){
|
||||
return ChannelRetMsg.waiting();
|
||||
}
|
||||
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
channelRetMsg.setChannelErrCode(response.getSubCode());
|
||||
channelRetMsg.setChannelErrMsg(response.getSubMsg());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.info("支付宝请求异常", e);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
channelRetMsg.setChannelErrMsg("支付宝请求异常");
|
||||
}
|
||||
|
||||
|
||||
return channelRetMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg query(TransferOrder transferOrder, MchAppConfigContext mchAppConfigContext) {
|
||||
AlipayFundTransCommonQueryRequest request = new AlipayFundTransCommonQueryRequest();
|
||||
AlipayFundTransCommonQueryModel model = new AlipayFundTransCommonQueryModel();
|
||||
model.setProductCode(TransferOrder.ENTRY_BANK_CARD.equals(transferOrder.getEntryType()) ? "TRANS_BANKCARD_NO_PWD" : "TRANS_ACCOUNT_NO_PWD");
|
||||
model.setBizScene("DIRECT_TRANSFER");
|
||||
model.setOutBizNo(transferOrder.getTransferId()); // 商户转账唯一订单号
|
||||
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, request, model);
|
||||
request.setBizModel(model);
|
||||
|
||||
// 调起支付宝接口
|
||||
AlipayFundTransCommonQueryResponse response = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).execute(request);
|
||||
if (response.isSuccess()) {
|
||||
// SUCCESS,明确成功
|
||||
if("SUCCESS".equalsIgnoreCase(response.getStatus())){
|
||||
return ChannelRetMsg.confirmSuccess(response.getOrderId());
|
||||
}
|
||||
// REFUND:退票(适用于"单笔转账到银行卡"); FAIL:失败(适用于"单笔转账到银行卡")
|
||||
else if ("REFUND".equalsIgnoreCase(response.getStatus()) || "FAIL".equalsIgnoreCase(response.getStatus())){
|
||||
return ChannelRetMsg.confirmFail(response.getErrorCode(), response.getFailReason());
|
||||
} else{
|
||||
return ChannelRetMsg.waiting();
|
||||
}
|
||||
} else {
|
||||
// 如果查询单号对应的数据不存在,那么数据不存在的原因可能是:(1)付款还在处理中;(2)付款处理失败导致付款订单没有落地,务必再次查询确认此次付款的结果。
|
||||
if("ORDER_NOT_EXIST".equalsIgnoreCase(response.getSubCode())){
|
||||
return ChannelRetMsg.waiting();
|
||||
}
|
||||
return ChannelRetMsg.confirmFail(AlipayKit.appendErrCode(response.getCode(), response.getSubCode()), AlipayKit.appendErrMsg(response.getMsg(), response.getSubMsg()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay.payway;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.domain.AlipayTradeAppPayModel;
|
||||
import com.alipay.api.request.AlipayTradeAppPayRequest;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliAppOrderRS;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 支付宝 APP支付
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:20
|
||||
*/
|
||||
@Service("alipayPaymentByAliAppService") //Service Name需保持全局唯一性
|
||||
public class AliApp extends AlipayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext){
|
||||
|
||||
AlipayTradeAppPayRequest req = new AlipayTradeAppPayRequest();
|
||||
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
|
||||
model.setOutTradeNo(payOrder.getPayOrderId());
|
||||
model.setSubject(payOrder.getSubject()); //订单标题
|
||||
model.setBody(payOrder.getBody()); //订单描述信息
|
||||
model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getFindAmt().toString())); //支付金额
|
||||
model.setTimeExpire(DateUtil.format(payOrder.getExpiredTime(), DatePattern.NORM_DATETIME_FORMAT)); // 订单超时时间
|
||||
req.setNotifyUrl(getNotifyUrl()); // 设置异步通知地址
|
||||
req.setBizModel(model);
|
||||
|
||||
//统一放置 isv接口必传信息
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, req, model);
|
||||
|
||||
|
||||
String payData = null;
|
||||
|
||||
// sdk方式需自行拦截接口异常信息
|
||||
try {
|
||||
payData = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).getAlipayClient().getAlipayClient().sdkExecute(req).getBody();
|
||||
} catch (AlipayApiException e) {
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}
|
||||
|
||||
// 构造函数响应数据
|
||||
AliAppOrderRS res = ApiResBuilder.buildSuccess(AliAppOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
//放置 响应数据
|
||||
channelRetMsg.setChannelAttach(payData);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
res.setPayData(payData);
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay.payway;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alipay.api.domain.AlipayTradePayModel;
|
||||
import com.alipay.api.request.AlipayTradePayRequest;
|
||||
import com.alipay.api.response.AlipayTradePayResponse;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliBarOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliBarOrderRS;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 支付宝 条码支付
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:20
|
||||
*/
|
||||
@Service("alipayPaymentByAliBarService") //Service Name需保持全局唯一性
|
||||
public class AliBar extends AlipayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
|
||||
AliBarOrderRQ bizRQ = (AliBarOrderRQ) rq;
|
||||
if(StringUtils.isEmpty(bizRQ.getAuthCode())){
|
||||
throw new BizException("用户支付条码[authCode]不可为空");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext){
|
||||
|
||||
AliBarOrderRQ bizRQ = (AliBarOrderRQ) rq;
|
||||
|
||||
AlipayTradePayRequest req = new AlipayTradePayRequest();
|
||||
AlipayTradePayModel model = new AlipayTradePayModel();
|
||||
model.setOutTradeNo(payOrder.getPayOrderId());
|
||||
model.setScene("bar_code"); //条码支付 bar_code ; 声波支付 wave_code
|
||||
model.setAuthCode(bizRQ.getAuthCode().trim()); //支付授权码
|
||||
model.setSubject(payOrder.getSubject()); //订单标题
|
||||
model.setBody(payOrder.getBody()); //订单描述信息
|
||||
model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getFindAmt().toString())); //支付金额
|
||||
model.setTimeExpire(DateUtil.format(payOrder.getExpiredTime(), DatePattern.NORM_DATETIME_FORMAT)); // 订单超时时间
|
||||
req.setNotifyUrl(getNotifyUrl()); // 设置异步通知地址
|
||||
req.setBizModel(model);
|
||||
|
||||
//统一放置 isv接口必传信息
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, req, model);
|
||||
|
||||
//调起支付宝 (如果异常, 将直接跑出 ChannelException )
|
||||
AlipayTradePayResponse alipayResp = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).execute(req);
|
||||
|
||||
// 构造函数响应数据
|
||||
AliBarOrderRS res = ApiResBuilder.buildSuccess(AliBarOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
//放置 响应数据
|
||||
channelRetMsg.setChannelAttach(alipayResp.getBody());
|
||||
channelRetMsg.setChannelOrderId(alipayResp.getTradeNo());
|
||||
channelRetMsg.setPlatformOrderNo(alipayResp.getTradeNo());
|
||||
channelRetMsg.setPlatformMchOrderNo(payOrder.getPayOrderId());
|
||||
channelRetMsg.setChannelUserId(alipayResp.getBuyerUserId()); //渠道用户标识
|
||||
|
||||
// ↓↓↓↓↓↓ 调起接口成功后业务判断务必谨慎!! 避免因代码编写bug,导致不能正确返回订单状态信息 ↓↓↓↓↓↓
|
||||
|
||||
//当条码重复发起时,支付宝返回的code = 10003, subCode = null [等待用户支付], 此时需要特殊判断 = = 。
|
||||
if("10000".equals(alipayResp.getCode()) && alipayResp.isSuccess()){ //支付成功, 更新订单成功 || 等待支付宝的异步回调接口
|
||||
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
|
||||
|
||||
}else if("10003".equals(alipayResp.getCode())){ //10003 表示为 处理中, 例如等待用户输入密码
|
||||
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
}else{ //其他状态, 表示下单失败
|
||||
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
channelRetMsg.setChannelErrCode(AlipayKit.appendErrCode(alipayResp.getCode(), alipayResp.getSubCode()));
|
||||
channelRetMsg.setChannelErrMsg(AlipayKit.appendErrMsg(alipayResp.getMsg(), alipayResp.getSubMsg()));
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay.payway;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alipay.api.domain.AlipayTradeCreateModel;
|
||||
import com.alipay.api.request.AlipayTradeCreateRequest;
|
||||
import com.alipay.api.response.AlipayTradeCreateResponse;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliJsapiOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliJsapiOrderRS;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 支付宝 jsapi支付
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:20
|
||||
*/
|
||||
@Service("alipayPaymentByJsapiService") //Service Name需保持全局唯一性
|
||||
public class AliJsapi extends AlipayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
|
||||
AliJsapiOrderRQ bizRQ = (AliJsapiOrderRQ) rq;
|
||||
if(StringUtils.isEmpty(bizRQ.getBuyerUserId())){
|
||||
throw new BizException("[buyerUserId]不可为空");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception{
|
||||
|
||||
AliJsapiOrderRQ bizRQ = (AliJsapiOrderRQ) rq;
|
||||
|
||||
AlipayTradeCreateRequest req = new AlipayTradeCreateRequest();
|
||||
AlipayTradeCreateModel model = new AlipayTradeCreateModel();
|
||||
model.setOutTradeNo(payOrder.getPayOrderId());
|
||||
model.setSubject(payOrder.getSubject()); //订单标题
|
||||
model.setBody(payOrder.getBody()); //订单描述信息
|
||||
model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getFindAmt().toString())); //支付金额
|
||||
model.setTimeExpire(DateUtil.format(payOrder.getExpiredTime(), DatePattern.NORM_DATETIME_FORMAT)); // 订单超时时间
|
||||
model.setBuyerId(bizRQ.getBuyerUserId());
|
||||
req.setNotifyUrl(getNotifyUrl()); // 设置异步通知地址
|
||||
req.setBizModel(model);
|
||||
|
||||
//统一放置 isv接口必传信息
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, req, model);
|
||||
|
||||
//调起支付宝 (如果异常, 将直接跑出 ChannelException )
|
||||
AlipayTradeCreateResponse alipayResp = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).execute(req);
|
||||
|
||||
// 构造函数响应数据
|
||||
AliJsapiOrderRS res = ApiResBuilder.buildSuccess(AliJsapiOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
//放置 响应数据
|
||||
channelRetMsg.setChannelAttach(alipayResp.getBody());
|
||||
|
||||
// ↓↓↓↓↓↓ 调起接口成功后业务判断务必谨慎!! 避免因代码编写bug,导致不能正确返回订单状态信息 ↓↓↓↓↓↓
|
||||
res.setAlipayTradeNo(alipayResp.getTradeNo());
|
||||
|
||||
channelRetMsg.setChannelOrderId(alipayResp.getTradeNo());
|
||||
if(alipayResp.isSuccess()){ //业务处理成功
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
}else{
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
channelRetMsg.setChannelErrCode(AlipayKit.appendErrCode(alipayResp.getCode(), alipayResp.getSubCode()));
|
||||
channelRetMsg.setChannelErrMsg(AlipayKit.appendErrMsg(alipayResp.getMsg(), alipayResp.getSubMsg()));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay.payway;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alipay.api.domain.AlipayTradeCreateModel;
|
||||
import com.alipay.api.request.AlipayTradeCreateRequest;
|
||||
import com.alipay.api.response.AlipayTradeCreateResponse;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.oauth2.AlipayOauth2Params;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliLiteOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliLiteOrderRS;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 支付宝 小程序支付
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:20
|
||||
*/
|
||||
@Service("alipayPaymentByLiteService") //Service Name需保持全局唯一性
|
||||
public class AliLite extends AlipayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
|
||||
AliLiteOrderRQ bizRQ = (AliLiteOrderRQ) rq;
|
||||
if(StringUtils.isEmpty(bizRQ.getBuyerUserId())){
|
||||
throw new BizException("[buyerUserId]不可为空");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception{
|
||||
|
||||
AliLiteOrderRQ bizRQ = (AliLiteOrderRQ) rq;
|
||||
|
||||
AlipayTradeCreateRequest req = new AlipayTradeCreateRequest();
|
||||
AlipayTradeCreateModel model = new AlipayTradeCreateModel();
|
||||
model.setOutTradeNo(payOrder.getPayOrderId());
|
||||
model.setSubject(payOrder.getSubject()); //订单标题
|
||||
model.setBody(payOrder.getBody()); //订单描述信息
|
||||
model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getFindAmt().toString())); //支付金额
|
||||
model.setTimeExpire(DateUtil.format(payOrder.getExpiredTime(), DatePattern.NORM_DATETIME_FORMAT)); // 订单超时时间
|
||||
model.setBuyerId(bizRQ.getBuyerUserId());
|
||||
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
AlipayOauth2Params oauth2Params = (AlipayOauth2Params) configContextQueryService.queryIsvOauth2Params(mchAppConfigContext.getMchApplyment().getIsvNo(), CS.IF_CODE.ALIPAY);
|
||||
model.setProductCode("JSAPI_PAY");
|
||||
model.setOpAppId(oauth2Params.getLiteParams().getAppId());
|
||||
|
||||
req.setNotifyUrl(getNotifyUrl()); // 设置异步通知地址
|
||||
req.setBizModel(model);
|
||||
|
||||
//统一放置 isv接口必传信息
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, req, model);
|
||||
|
||||
//调起支付宝 (如果异常, 将直接跑出 ChannelException )
|
||||
AlipayTradeCreateResponse alipayResp = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).execute(req);
|
||||
|
||||
// 构造函数响应数据
|
||||
AliLiteOrderRS res = ApiResBuilder.buildSuccess(AliLiteOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
//放置 响应数据
|
||||
channelRetMsg.setChannelAttach(alipayResp.getBody());
|
||||
|
||||
// ↓↓↓↓↓↓ 调起接口成功后业务判断务必谨慎!! 避免因代码编写bug,导致不能正确返回订单状态信息 ↓↓↓↓↓↓
|
||||
res.setAlipayTradeNo(alipayResp.getTradeNo());
|
||||
|
||||
channelRetMsg.setChannelOrderId(alipayResp.getTradeNo());
|
||||
if(alipayResp.isSuccess()){ //业务处理成功
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
}else{
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
channelRetMsg.setChannelErrCode(AlipayKit.appendErrCode(alipayResp.getCode(), alipayResp.getSubCode()));
|
||||
channelRetMsg.setChannelErrMsg(AlipayKit.appendErrMsg(alipayResp.getMsg(), alipayResp.getSubMsg()));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay.payway;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.domain.AlipayTradePagePayModel;
|
||||
import com.alipay.api.request.AlipayTradePagePayRequest;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliPcOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliPcOrderRS;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 支付宝 PC支付
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:21
|
||||
*/
|
||||
@Service("alipayPaymentByAliPcService") //Service Name需保持全局唯一性
|
||||
public class AliPc extends AlipayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext){
|
||||
|
||||
AliPcOrderRQ bizRQ = (AliPcOrderRQ) rq;
|
||||
|
||||
AlipayTradePagePayRequest req = new AlipayTradePagePayRequest();
|
||||
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
|
||||
model.setOutTradeNo(payOrder.getPayOrderId());
|
||||
model.setSubject(payOrder.getSubject()); //订单标题
|
||||
model.setBody(payOrder.getBody()); //订单描述信息
|
||||
model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getFindAmt().toString())); //支付金额
|
||||
model.setTimeExpire(DateUtil.format(payOrder.getExpiredTime(), DatePattern.NORM_DATETIME_FORMAT)); // 订单超时时间
|
||||
model.setProductCode("FAST_INSTANT_TRADE_PAY");
|
||||
model.setQrPayMode("2"); //订单码-跳转模式
|
||||
req.setNotifyUrl(getNotifyUrl()); // 设置异步通知地址
|
||||
req.setReturnUrl(getReturnUrl()); // 同步跳转地址
|
||||
req.setBizModel(model);
|
||||
|
||||
//统一放置 isv接口必传信息
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, req, model);
|
||||
|
||||
// 构造函数响应数据
|
||||
AliPcOrderRS res = ApiResBuilder.buildSuccess(AliPcOrderRS.class);
|
||||
|
||||
try {
|
||||
if(CS.PAY_DATA_TYPE.FORM.equals(bizRQ.getPayDataType())){
|
||||
res.setFormContent(configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).getAlipayClient().getAlipayClient().pageExecute(req).getBody());
|
||||
}else{
|
||||
res.setPayUrl(configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).getAlipayClient().getAlipayClient().pageExecute(req, "GET").getBody());
|
||||
}
|
||||
}catch (AlipayApiException e) {
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}
|
||||
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
//放置 响应数据
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay.payway;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alipay.api.domain.AlipayTradePrecreateModel;
|
||||
import com.alipay.api.request.AlipayTradePrecreateRequest;
|
||||
import com.alipay.api.response.AlipayTradePrecreateResponse;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliQrOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliQrOrderRS;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 支付宝 QR支付
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:21
|
||||
*/
|
||||
@Service("alipayPaymentByAliQrService") //Service Name需保持全局唯一性
|
||||
public class AliQr extends AlipayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext){
|
||||
|
||||
AliQrOrderRQ aliQrOrderRQ = (AliQrOrderRQ)rq;
|
||||
|
||||
AlipayTradePrecreateRequest req = new AlipayTradePrecreateRequest();
|
||||
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
|
||||
model.setOutTradeNo(payOrder.getPayOrderId());
|
||||
model.setSubject(payOrder.getSubject()); //订单标题
|
||||
model.setBody(payOrder.getBody()); //订单描述信息
|
||||
model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getFindAmt().toString())); //支付金额
|
||||
model.setTimeExpire(DateUtil.format(payOrder.getExpiredTime(), DatePattern.NORM_DATETIME_FORMAT)); // 订单超时时间
|
||||
req.setNotifyUrl(getNotifyUrl()); // 设置异步通知地址
|
||||
req.setBizModel(model);
|
||||
|
||||
//统一放置 isv接口必传信息
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, req, model);
|
||||
|
||||
//调起支付宝 (如果异常, 将直接跑出 ChannelException )
|
||||
AlipayTradePrecreateResponse alipayResp = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).execute(req);
|
||||
|
||||
// 构造函数响应数据
|
||||
AliQrOrderRS res = ApiResBuilder.buildSuccess(AliQrOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
//放置 响应数据
|
||||
channelRetMsg.setChannelAttach(alipayResp.getBody());
|
||||
|
||||
// ↓↓↓↓↓↓ 调起接口成功后业务判断务必谨慎!! 避免因代码编写bug,导致不能正确返回订单状态信息 ↓↓↓↓↓↓
|
||||
|
||||
if(alipayResp.isSuccess()){ //处理成功
|
||||
|
||||
if(CS.PAY_DATA_TYPE.CODE_IMG_URL.equals(aliQrOrderRQ.getPayDataType())){ //二维码地址
|
||||
res.setCodeImgUrl(sysConfigService.getDBApplicationConfig().genScanImgUrl(alipayResp.getQrCode()));
|
||||
|
||||
}else{ //默认都为跳转地址方式
|
||||
res.setCodeUrl(alipayResp.getQrCode());
|
||||
}
|
||||
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
}else{ //其他状态, 表示下单失败
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
channelRetMsg.setChannelErrCode(AlipayKit.appendErrCode(alipayResp.getCode(), alipayResp.getSubCode()));
|
||||
channelRetMsg.setChannelErrMsg(AlipayKit.appendErrMsg(alipayResp.getMsg(), alipayResp.getSubMsg()));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.alipay.payway;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.domain.AlipayTradeWapPayModel;
|
||||
import com.alipay.api.request.AlipayTradeWapPayRequest;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliWapOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliWapOrderRS;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.alipay.AlipayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 支付宝 wap支付
|
||||
*
|
||||
* @author terrfly
|
||||
*
|
||||
* @date 2021/6/8 17:21
|
||||
*/
|
||||
@Service("alipayPaymentByAliWapService") //Service Name需保持全局唯一性
|
||||
public class AliWap extends AlipayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext){
|
||||
|
||||
AliWapOrderRQ bizRQ = (AliWapOrderRQ)rq;
|
||||
|
||||
AlipayTradeWapPayRequest req = new AlipayTradeWapPayRequest();
|
||||
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
|
||||
model.setOutTradeNo(payOrder.getPayOrderId());
|
||||
model.setSubject(payOrder.getSubject()); //订单标题
|
||||
model.setBody(payOrder.getBody()); //订单描述信息
|
||||
model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getFindAmt().toString())); //支付金额
|
||||
model.setTimeExpire(DateUtil.format(payOrder.getExpiredTime(), DatePattern.NORM_DATETIME_FORMAT)); // 订单超时时间
|
||||
model.setProductCode("QUICK_WAP_PAY");
|
||||
req.setNotifyUrl(getNotifyUrl()); // 设置异步通知地址
|
||||
req.setReturnUrl(getReturnUrl()); // 同步跳转地址
|
||||
req.setBizModel(model);
|
||||
|
||||
//统一放置 isv接口必传信息
|
||||
AlipayKit.putApiIsvInfo(mchAppConfigContext, req, model);
|
||||
|
||||
// 构造函数响应数据
|
||||
AliWapOrderRS res = ApiResBuilder.buildSuccess(AliWapOrderRS.class);
|
||||
|
||||
try {
|
||||
if(CS.PAY_DATA_TYPE.FORM.equals(bizRQ.getPayDataType())){ //表单方式
|
||||
res.setFormContent(configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).getAlipayClient().getAlipayClient().pageExecute(req).getBody());
|
||||
|
||||
}else if (CS.PAY_DATA_TYPE.CODE_IMG_URL.equals(bizRQ.getPayDataType())){ //二维码图片地址
|
||||
|
||||
String payUrl = configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).getAlipayClient().getAlipayClient().pageExecute(req, "GET").getBody();
|
||||
res.setCodeImgUrl(sysConfigService.getDBApplicationConfig().genScanImgUrl(payUrl));
|
||||
}else{ // 默认都为 payUrl方式
|
||||
|
||||
res.setPayUrl(configContextQueryService.getAlipayClientWrapper(mchAppConfigContext).getAlipayClient().getAlipayClient().pageExecute(req, "GET").getBody());
|
||||
}
|
||||
}catch (AlipayApiException e) {
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}
|
||||
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
//放置 响应数据
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,477 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.entity.MchInfo;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvsubMchParams;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayNormalMchParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.core.utils.DateKit;
|
||||
import com.jeequan.jeepay.core.utils.ImageUtils;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.Cleanup;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 支付通道工具包
|
||||
*
|
||||
* @author xiaoyu
|
||||
* @date 2022/6/6 11:00
|
||||
*/
|
||||
@Slf4j
|
||||
public class DgPayKit {
|
||||
|
||||
public static final String STATE_SUCCESS = "00000000";
|
||||
public static final String STATE_ING = "00000100";
|
||||
public static final String BIZ_SUCCESS = "SUCCESS";
|
||||
public static final String STATE_ING_P = "P";
|
||||
public static final String STATE_SUCCESS_S = "S";
|
||||
public static final String STATE_FAIL_F = "F";
|
||||
|
||||
public static final String BASE_REQ_URL = "https://api.huifu.com/v2";
|
||||
/**
|
||||
* 企业商户进件请求地址
|
||||
**/
|
||||
public static final String MCH_APPLY_ENT_URL = "/merchant/basicdata/ent";
|
||||
/**
|
||||
* 个人商户进件请求地址
|
||||
**/
|
||||
public static final String MCH_APPLY_INDV_URL = "/merchant/basicdata/indv";
|
||||
/**
|
||||
* 商户信息修改
|
||||
**/
|
||||
public static final String MCH_APPLY_MODIFY_URL = "/merchant/basicdata/modify";
|
||||
public static final String MCH_APPLY_UPDATE_URL = "/merchant/integrate/update";
|
||||
/**
|
||||
* 进件状态查询
|
||||
**/
|
||||
public static final String MCH_APPLY_QUERY_URL = "/merchant/basicdata/status/query";
|
||||
/**
|
||||
* 商户详细信息查询
|
||||
**/
|
||||
public static final String MCH_INFO_QUERY_URL = "/merchant/basicdata/query";
|
||||
/**
|
||||
* 图片上传
|
||||
**/
|
||||
public static final String MCH_UPLOAD_PICTURE_URL = "/supplementary/picture";
|
||||
/**
|
||||
* 商户业务开通
|
||||
**/
|
||||
public static final String MCH_BUSI_OPEN_URL = "/merchant/busi/open";
|
||||
/**
|
||||
* 微信商户配置
|
||||
**/
|
||||
public static final String MCH_BUSI_CONFIG_URL = "/merchant/busi/config";
|
||||
/**
|
||||
* 结算信息查询
|
||||
**/
|
||||
public static final String MCH_BUSI_SETTLE_QUERY_URL = "/merchant/basicdata/settlement/query";
|
||||
/**
|
||||
* 智能POS webhook 支付推送事件类型
|
||||
**/
|
||||
public static List<String> POS_PAY_EVENT = new ArrayList<>();
|
||||
|
||||
static {
|
||||
POS_PAY_EVENT.add("pay.union_scaned");
|
||||
POS_PAY_EVENT.add("pay.wx_scaned");
|
||||
POS_PAY_EVENT.add("pay.ali_scaned");
|
||||
POS_PAY_EVENT.add("pay.digit_scaned");
|
||||
POS_PAY_EVENT.add("pay.card_consume.pos");
|
||||
}
|
||||
|
||||
/**
|
||||
* 智能POS webhook 退款推送事件类型
|
||||
**/
|
||||
public static List<String> POS_REFUND_EVENT = new ArrayList<>();
|
||||
|
||||
static {
|
||||
POS_REFUND_EVENT.add("refund.card_consume.pos");
|
||||
POS_REFUND_EVENT.add("refund.standard");
|
||||
}
|
||||
|
||||
/**
|
||||
* 重写请求方法
|
||||
*
|
||||
* @param reqUrl
|
||||
* @param bizData
|
||||
* @return
|
||||
*/
|
||||
public static JSONObject req(String reqUrl, DgpayIsvParams isvParams, JSONObject bizData) {
|
||||
JSONObject reqParams = initReq(isvParams, bizData);
|
||||
// 生成签名
|
||||
TreeMap treeMap = JSON.parseObject(bizData.toJSONString(), TreeMap.class);
|
||||
JSONObject treeJson = (JSONObject) JSON.toJSON(treeMap);
|
||||
String sign = sign(treeJson.toJSONString(), isvParams.getRsaPrivateKey());
|
||||
reqParams.put("sign", sign);
|
||||
String requestUrl = BASE_REQ_URL + reqUrl;
|
||||
log.info("【斗拱】请求地址:{},请求参数:{}", requestUrl, reqParams);
|
||||
HttpResponse response = post(requestUrl, reqParams.toJSONString());
|
||||
log.info("【斗拱】响应结果:{}", response.body());
|
||||
return initResult(response.body(), isvParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理统一响应结果
|
||||
*
|
||||
* @param result
|
||||
* @return
|
||||
*/
|
||||
private static JSONObject initResult(String result, DgpayIsvParams isvParams) {
|
||||
JSONObject respData = JSON.parseObject(result);
|
||||
JSONObject bizData = respData.getJSONObject("data");
|
||||
TreeMap signData = JSON.parseObject(JSON.toJSONString(bizData), TreeMap.class);
|
||||
boolean verifyResult = DgPayKit.verify(JSON.toJSONString(signData), isvParams.getRsaPublicKey(), respData.getString("sign"));
|
||||
if (!verifyResult) {
|
||||
throw new BizException("签名校验异常");
|
||||
}
|
||||
if (!DgPayKit.STATE_SUCCESS.equals(bizData.getString("resp_code"))) {
|
||||
throw new BizException(bizData.getString("resp_desc"));
|
||||
}
|
||||
return bizData;
|
||||
}
|
||||
|
||||
public static JSONObject initReq(DgpayIsvParams isvParams, JSONObject bizData) {
|
||||
JSONObject reqParams = new JSONObject();
|
||||
reqParams.put("sys_id", isvParams.getSysId());
|
||||
reqParams.put("product_id", isvParams.getProductId());
|
||||
reqParams.put("data", bizData);
|
||||
return reqParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* 放置 请求信息
|
||||
**/
|
||||
public static JSONObject request(MchAppConfigContext mchAppConfigContext, JSONObject dataParams, String reqUrl, String ifCode) {
|
||||
//
|
||||
dataParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
dataParams.put("req_seq_id", DateKit.currentTimeMillis());
|
||||
|
||||
try {
|
||||
|
||||
JSONObject configParams = getConfigParams(mchAppConfigContext, ifCode);
|
||||
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 请求参数带参
|
||||
reqParams.put("sys_id", configParams.getString("sysId"));
|
||||
reqParams.put("product_id", configParams.getString("productId"));
|
||||
if (dataParams.getBoolean("noMchId") != null && dataParams.getBoolean("noMchId")) {
|
||||
} else {
|
||||
if (StringUtils.isEmpty(dataParams.getString("huifu_id")) && StringUtils.isNotEmpty(configParams.getString("huifuId"))) {
|
||||
dataParams.put("huifu_id", configParams.getString("huifuId"));
|
||||
}
|
||||
}
|
||||
dataParams.remove("noMchId");
|
||||
// 请求数据
|
||||
reqParams.put("data", dataParams);
|
||||
// 生成签名
|
||||
TreeMap treeMap = JSON.parseObject(dataParams.toJSONString(), TreeMap.class);
|
||||
JSONObject treeJson = (JSONObject) JSON.toJSON(treeMap);
|
||||
String sign = sign(treeJson.toJSONString(), configParams.getString("rsaPrivateKey"));
|
||||
reqParams.put("sign", sign);
|
||||
String requestUrl = BASE_REQ_URL + reqUrl;
|
||||
log.info("【斗拱】请求地址:{},请求参数:{}", requestUrl, reqParams);
|
||||
HttpResponse response = post(requestUrl, reqParams.toJSONString());
|
||||
String res = response.body();
|
||||
log.info("【斗拱】响应结果:{}", res);
|
||||
return JSON.parseObject(res);
|
||||
} catch (BizException e) {
|
||||
throw new BizException("[斗拱支付]参数请求异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付请求
|
||||
**/
|
||||
public static JSONObject payRequest(MchAppConfigContext mchAppConfigContext, JSONObject dataParams, String reqUrl, String ifCode) {
|
||||
JSONObject configParams = getConfigParams(mchAppConfigContext, ifCode);
|
||||
dataParams.put("channel_no", configParams.getString("channelNo"));
|
||||
dataParams.put("pay_scene", configParams.getString("payScene"));
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 请求参数带参
|
||||
reqParams.put("sys_id", configParams.getString("sysId"));
|
||||
reqParams.put("product_id", configParams.getString("productId"));
|
||||
if (dataParams.getBoolean("noMchId") != null && dataParams.getBoolean("noMchId")) {
|
||||
} else {
|
||||
if (StringUtils.isEmpty(dataParams.getString("huifu_id")) && StringUtils.isNotEmpty(configParams.getString("huifuId"))) {
|
||||
dataParams.put("huifu_id", configParams.getString("huifuId"));
|
||||
}
|
||||
}
|
||||
dataParams.remove("noMchId");
|
||||
// 请求数据
|
||||
reqParams.put("data", dataParams);
|
||||
// 生成签名
|
||||
TreeMap treeMap = JSON.parseObject(dataParams.toJSONString(), TreeMap.class);
|
||||
JSONObject treeJson = (JSONObject) JSON.toJSON(treeMap);
|
||||
String sign = sign(treeJson.toJSONString(), configParams.getString("rsaPrivateKey"));
|
||||
reqParams.put("sign", sign);
|
||||
String requestUrl = BASE_REQ_URL + reqUrl;
|
||||
log.info("【斗拱】请求地址:{},请求参数:{}", requestUrl, reqParams);
|
||||
HttpResponse response = post(requestUrl, reqParams.toJSONString());
|
||||
String res = response.body();
|
||||
log.info("【斗拱】响应结果:{}", res);
|
||||
JSONObject resp = JSON.parseObject(res);
|
||||
JSONObject data = resp.getJSONObject("data");
|
||||
if (!STATE_SUCCESS.equals(data.getString("resp_code")) && !STATE_ING.equals(data.getString("resp_code"))) {
|
||||
String msg = StringUtils.isNotEmpty(data.getString("bank_message")) ? data.getString("bank_message") : data.getString("resp_desc");
|
||||
throw new BizException(msg);
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 放置 请求信息
|
||||
**/
|
||||
public static String uploadFile(String isvNo, String fileType, String fileUrl, String ifCode) {
|
||||
try {
|
||||
if (StringUtils.isEmpty(fileUrl)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(new MchApplyment().setIsvNo(isvNo));
|
||||
|
||||
JSONObject configParams = getConfigParams(mchAppConfigContext, ifCode);
|
||||
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 请求参数带参
|
||||
reqParams.put("product_id", configParams.getString("productId"));
|
||||
reqParams.put("sys_id", configParams.getString("sysId"));
|
||||
|
||||
JSONObject dataParams = new JSONObject();
|
||||
dataParams.put("req_seq_id", DateKit.currentTimeMillis());
|
||||
dataParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
dataParams.put("file_type", fileType);
|
||||
dataParams.put("picture", "1.jpg");
|
||||
// 请求数据
|
||||
reqParams.put("data", dataParams);
|
||||
// 生成签名
|
||||
TreeMap treeMap = JSON.parseObject(dataParams.toJSONString(), TreeMap.class);
|
||||
JSONObject treeJson = (JSONObject) JSON.toJSON(treeMap);
|
||||
String sign = sign(treeJson.toJSONString(), configParams.getString("rsaPrivateKey"));
|
||||
reqParams.put("sign", sign);
|
||||
String requestUrl = BASE_REQ_URL + MCH_UPLOAD_PICTURE_URL;
|
||||
log.info("【斗拱】上传图片,请求地址:{},请求参数:{}", requestUrl, reqParams);
|
||||
|
||||
// 下载文件
|
||||
byte[] imgFileByteArray = null;
|
||||
try {
|
||||
ByteArrayOutputStream baos = ImageUtils.compressNetPic(fileUrl, 2048 * 1024);
|
||||
imgFileByteArray = baos.toByteArray();
|
||||
} catch (IORuntimeException e) {
|
||||
log.info("斗拱入网压缩图片异常, 图片链接为{}", fileUrl, e);
|
||||
throw new BizException("银盛入网压缩图片失败, " + e.getMessage());
|
||||
}
|
||||
|
||||
@Cleanup HttpResponse response = HttpUtil.createPost(requestUrl)
|
||||
.form("picture", imgFileByteArray, "1.jpg")
|
||||
.form("sys_id", configParams.getString("sysId"))
|
||||
.form("product_id", configParams.getString("productId"))
|
||||
.form("sign", sign)
|
||||
.form("data", dataParams.toJSONString())
|
||||
.execute();
|
||||
String result = response.body();
|
||||
log.info("【斗拱】上传图片,响应结果:{}", result);
|
||||
JSONObject resJson = JSON.parseObject(result);
|
||||
JSONObject resData = resJson.getJSONObject("data");
|
||||
String respCode = resData.getString("resp_code");
|
||||
String respDesc = resData.getString("resp_desc");
|
||||
if (!DgPayKit.STATE_SUCCESS.equals(respCode)) {
|
||||
throw new BizException(respDesc);
|
||||
}
|
||||
|
||||
return resData.getString("file_id");
|
||||
} catch (Exception e) {
|
||||
throw new BizException("[斗拱支付]上传文件请求异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 公共参数
|
||||
**/
|
||||
public static JSONObject dataParams(PayOrder payOrder, String notifyUrl) {
|
||||
JSONObject dataParams = new JSONObject();
|
||||
// 请求日期
|
||||
dataParams.put("req_date", DateUtil.format(payOrder.getCreatedAt(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
dataParams.put("req_seq_id", payOrder.getPayOrderId());
|
||||
// 支付金额 元 保留两位小数
|
||||
dataParams.put("trans_amt", AmountUtil.convertCent2Dollar(payOrder.getFindAmt()));
|
||||
// 商品描述
|
||||
dataParams.put("goods_desc", payOrder.getBody());
|
||||
|
||||
// 安全信息
|
||||
JSONObject riskJson = new JSONObject();
|
||||
riskJson.put("ip_addr", payOrder.getClientIp());
|
||||
dataParams.put("risk_check_data", riskJson.toJSONString());
|
||||
// 订单失效时间
|
||||
dataParams.put("time_expire", DateUtil.format(payOrder.getExpiredTime(), DatePattern.PURE_DATETIME_PATTERN));
|
||||
// 异步回调地址
|
||||
dataParams.put("notify_url", notifyUrl);
|
||||
return dataParams;
|
||||
}
|
||||
|
||||
|
||||
public static JSONObject getConfigParams(MchAppConfigContext mchAppConfigContext, String ifCode) {
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
|
||||
JSONObject configJson = null;
|
||||
// 特约商户
|
||||
if (mchAppConfigContext.isIsvsubMch()) {
|
||||
DgpayIsvParams isvParams;
|
||||
isvParams = (DgpayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment().getIsvNo(), ifCode);
|
||||
|
||||
if (isvParams == null) {
|
||||
throw new BizException("服务商参数未配置");
|
||||
}
|
||||
|
||||
configJson = (JSONObject) JSON.toJSON(isvParams);
|
||||
|
||||
DgpayIsvsubMchParams mchParams = (DgpayIsvsubMchParams) configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), ifCode);
|
||||
if (mchParams != null) {
|
||||
configJson.put("huifuId", mchAppConfigContext.getMchApplyment().getChannelMchNo());
|
||||
configJson.put("payScene", StringUtils.defaultString(mchParams.getPayScene(), "02"));
|
||||
}
|
||||
|
||||
configJson.put("productId", isvParams.getProductId());
|
||||
configJson.put("channelNo", isvParams.getChannelNo());
|
||||
} else {
|
||||
// 普通商户
|
||||
DgpayNormalMchParams mchParams = (DgpayNormalMchParams) configContextQueryService.queryNormalMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), ifCode);
|
||||
if (mchParams == null) {
|
||||
throw new BizException("商户参数未配置");
|
||||
}
|
||||
|
||||
configJson = (JSONObject) JSON.toJSON(mchParams);
|
||||
configJson.put("sysId", mchParams.getHuifuId());
|
||||
configJson.put("productId", mchParams.getProductId());
|
||||
configJson.put("payScene", StringUtils.defaultString(mchParams.getPayScene(), "02"));
|
||||
}
|
||||
return configJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author: xiaoyu
|
||||
* @date: 2022/4/13 15:43
|
||||
* @describe: 发送请求
|
||||
*/
|
||||
public static HttpResponse post(String url, String params) {
|
||||
HttpResponse response = HttpUtil.createPost(url)
|
||||
.header("content-type", "application/json;charset=utf-8")
|
||||
.timeout(20000)
|
||||
.charset("utf-8")
|
||||
.body(params)
|
||||
.execute();
|
||||
return response;
|
||||
}
|
||||
|
||||
public static String sign(String data, String privateKeyBase64) {
|
||||
try {
|
||||
byte[] bytes = Base64.getDecoder().decode(privateKeyBase64);
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
|
||||
Signature signature = Signature.getInstance("SHA256WithRSA");
|
||||
signature.initSign(privateKey);
|
||||
signature.update(data.getBytes(StandardCharsets.UTF_8));
|
||||
return Base64.getEncoder().encodeToString(signature.sign());
|
||||
} catch (Exception var7) {
|
||||
var7.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RSA公钥验签
|
||||
*
|
||||
* @param data 待签名字符串
|
||||
* @param publicKeyBase64 公钥(Base64编码)
|
||||
* @return 验签结果
|
||||
* @throws Exception
|
||||
*/
|
||||
public static boolean verify(String data, String publicKeyBase64, String sign) {
|
||||
// Base64 --> Key
|
||||
try {
|
||||
byte[] bytes = Base64.getDecoder().decode(publicKeyBase64);
|
||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
|
||||
KeyFactory keyFactory;
|
||||
keyFactory = KeyFactory.getInstance("RSA");
|
||||
PublicKey publicKey = keyFactory.generatePublic(keySpec);
|
||||
// verify
|
||||
Signature signature = Signature.getInstance("SHA256WithRSA");
|
||||
signature.initVerify(publicKey);
|
||||
signature.update(data.getBytes(StandardCharsets.UTF_8));
|
||||
return signature.verify(Base64.getDecoder().decode(sign));
|
||||
} catch (Exception e) {
|
||||
log.error("Exception", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换
|
||||
*/
|
||||
public static String covertChannelId(String channelType) {
|
||||
return StringUtils.defaultIfBlank(channelType, CS.AUTO_POS_PAY_TYPE.CARD).toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换
|
||||
*/
|
||||
public static String covertMobilePayType(String payType) {
|
||||
switch (payType) {
|
||||
case CS.AUTO_POS_PAY_CHANNEL.ALIPAY:
|
||||
return "A";
|
||||
case CS.AUTO_POS_PAY_CHANNEL.WECHAT:
|
||||
return "W";
|
||||
case CS.AUTO_POS_PAY_CHANNEL.QR_CASHIER:
|
||||
return "J";
|
||||
case CS.AUTO_POS_PAY_CHANNEL.DCEP:
|
||||
return "D";
|
||||
default:
|
||||
return "U";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 异常信息返回描述处理
|
||||
**/
|
||||
public static void channelMsgError(JSONObject resData, ChannelRetMsg channelRetMsg) {
|
||||
if (StringUtils.isEmpty(resData.getString("bank_message"))) {
|
||||
|
||||
channelRetMsg.setChannelErrMsg(resData.get("resp_desc").toString());
|
||||
channelRetMsg.setChannelErrCode(resData.get("resp_code").toString());
|
||||
} else {
|
||||
|
||||
channelRetMsg.setChannelErrMsg(resData.getString("bank_message"));
|
||||
channelRetMsg.setChannelErrCode(resData.get("bank_code").toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.entity.MchInfo;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IDgApplymentApiService;
|
||||
import com.jeequan.jeepay.core.model.applyment.DgpayApplymentInfo;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvsubMchParams;
|
||||
import com.jeequan.jeepay.core.utils.DateKit;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.service.impl.RateConfigService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 斗拱 接口
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/6/9 9:25
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DgpayApplymentApiService implements IDgApplymentApiService {
|
||||
|
||||
@Autowired
|
||||
protected SysConfigService sysConfigService;
|
||||
@Autowired
|
||||
protected RateConfigService rateConfigService;
|
||||
|
||||
@Override
|
||||
public MchApplyment dgpayConfigOpen(MchApplyment mchApplyment, JSONObject paramJSON) {
|
||||
String logPrefix = "【斗拱商户分账配置】";
|
||||
MchApplyment result = new MchApplyment();
|
||||
try {
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB)
|
||||
.setMchApplyment(mchApplyment);
|
||||
JSONObject succResJson = JSON.parseObject(mchApplyment.getSuccResParameter());
|
||||
if (succResJson == null || StringUtils.isEmpty(succResJson.getString("huifuId"))) {
|
||||
result.setApplyErrorInfo("无汇付商户号(huifu_id),请确认是否进件成功");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 最大分账比例
|
||||
String applyRatio = paramJSON.getString("applyRatio");
|
||||
if (StringUtils.isEmpty(applyRatio)) {
|
||||
result.setApplyErrorInfo("请填写最大分账比例");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 进件商户号
|
||||
String huifuId = succResJson.getString("huifuId");
|
||||
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 汇付ID
|
||||
reqParams.put("huifu_id", huifuId);
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis() + "");
|
||||
// 分账规则来源 01-接口发起 02-控台配置
|
||||
reqParams.put("rule_origin", "01");
|
||||
// 分账是否支持撤销交易
|
||||
reqParams.put("repeal_flag", "Y");
|
||||
// 分账是否支持退货交易
|
||||
reqParams.put("refund_flag", "Y");
|
||||
// 分账开关
|
||||
reqParams.put("div_flag", "Y");
|
||||
|
||||
// 最大分账比例 未填写分账比例不请求开通分账
|
||||
reqParams.put("apply_ratio", applyRatio);
|
||||
// 生效类型
|
||||
reqParams.put("start_type", "0");
|
||||
|
||||
// 发送请求
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/merchant/split/config", mchApplyment.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
log.info("{} 响应结果:resData={}", logPrefix, resData);
|
||||
|
||||
if (!"00000000".equals(resData.getString("resp_code"))) {
|
||||
result.setApplyErrorInfo(resData.getString("resp_desc"));
|
||||
}
|
||||
|
||||
result.setChannelVar1(paramJSON.toJSONString());
|
||||
|
||||
} catch (BizException e) {
|
||||
result.setApplyErrorInfo("[" + e.getMessage() + "]");
|
||||
log.error("{} 操作失败:", logPrefix, e);
|
||||
} catch (Exception e) {
|
||||
result.setApplyErrorInfo("[" + e.getMessage() + "]");
|
||||
log.error("{} 操作失败:", logPrefix, e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MchApplyment dgpayConfigOpenQuery(MchApplyment mchApplyment) {
|
||||
String logPrefix = "【斗拱商户分账配置查询】";
|
||||
MchApplyment result = new MchApplyment();
|
||||
try {
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(mchApplyment);
|
||||
JSONObject succResJson = JSON.parseObject(mchApplyment.getSuccResParameter());
|
||||
if (succResJson == null || StringUtils.isEmpty(succResJson.getString("huifuId"))) {
|
||||
result.setApplyErrorInfo("无汇付商户号(huifu_id),请确认是否进件成功");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 进件商户号
|
||||
String huifuId = succResJson.getString("huifuId");
|
||||
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 汇付ID
|
||||
reqParams.put("huifu_id", huifuId);
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis() + "_" + huifuId);
|
||||
|
||||
// 发送请求
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/merchant/split/query", mchApplyment.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
log.info("{} 响应结果:resData={}", logPrefix, resData);
|
||||
|
||||
result.setChannelVar2(resData.toJSONString());
|
||||
|
||||
} catch (BizException e) {
|
||||
result.setApplyErrorInfo("[" + e.getMessage() + "]");
|
||||
log.error("{} 操作失败:", logPrefix, e);
|
||||
} catch (Exception e) {
|
||||
result.setApplyErrorInfo("[" + e.getMessage() + "]");
|
||||
log.error("{} 操作失败:", logPrefix, e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MchApplyment wechatConfigSet(String isvNo, String mchNo, String appId, String jsapiPath, String feeType, String configWxBindLiteAppId, String configWxBindAppId, String bankChannelNo, String ifCode) {
|
||||
String logPrefix = "【斗拱商户微信配置】";
|
||||
MchApplyment result = new MchApplyment();
|
||||
try {
|
||||
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
// 获取支付参数
|
||||
DgpayIsvParams isvParams = (DgpayIsvParams) configContextQueryService.queryIsvParams(isvNo, ifCode);
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB).setMchApplyment(new MchApplyment().setIsvNo(isvNo));
|
||||
|
||||
DgpayIsvsubMchParams mchParams = (DgpayIsvsubMchParams) configContextQueryService.queryIsvsubMchParams(mchNo, appId, ifCode);
|
||||
|
||||
if (mchParams == null || StringUtils.isEmpty(mchParams.getHuifuId())) {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo("商户参数未配置,请先配置商户应用参数");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 进件商户号
|
||||
String huifuId = mchParams.getHuifuId();
|
||||
|
||||
// 请求参数
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 汇付ID
|
||||
reqParams.put("huifu_id", huifuId);
|
||||
// 产品编号
|
||||
reqParams.put("product_id", isvParams.getProductId());
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis() + "");
|
||||
|
||||
// 业务开通类型
|
||||
reqParams.put("fee_type", feeType);
|
||||
// 授权目录
|
||||
reqParams.put("wx_woa_path", jsapiPath);
|
||||
// 微信小程序APPID
|
||||
reqParams.put("wx_applet_app_id", configWxBindLiteAppId);
|
||||
// 公众号APPID
|
||||
reqParams.put("wx_woa_app_id", configWxBindAppId);
|
||||
if (StringUtils.isNotEmpty(bankChannelNo)) {
|
||||
// 渠道号
|
||||
reqParams.put("bank_channel_no", bankChannelNo);
|
||||
}
|
||||
|
||||
// 发送请求
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, DgPayKit.MCH_BUSI_CONFIG_URL, ifCode);
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
if (DgPayKit.STATE_SUCCESS.equals(code)) {
|
||||
result.setState(MchApplyment.STATE_SUCCESS);
|
||||
} else {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo(code + "[" + resData.getString("resp_desc") + "]");
|
||||
log.error("{} 请求失败:code={}, msg={}", logPrefix, code, resData.getString("resp_desc"));
|
||||
return result;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo("[" + e.getMessage() + "]");
|
||||
log.error("{} 配置异常:", logPrefix, e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MchApplyment wechatRealName(MchApplyment mchApplyment) {
|
||||
String logPrefix = "【斗拱商户微信实名认证】";
|
||||
MchApplyment result = new MchApplyment();
|
||||
try {
|
||||
// 获取支付参数
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(mchApplyment);
|
||||
JSONObject succResJson = JSON.parseObject(mchApplyment.getSuccResParameter());
|
||||
if (succResJson == null || StringUtils.isEmpty(succResJson.getString("huifuId"))) {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo("商户参数未配置,请先配置商户应用参数");
|
||||
return result;
|
||||
}
|
||||
// 进件商户号
|
||||
String huifuId = succResJson.getString("huifuId");
|
||||
|
||||
// 获取详细参数
|
||||
DgpayApplymentInfo info = JSON.parseObject(mchApplyment.getApplyDetailInfo(), DgpayApplymentInfo.class);
|
||||
|
||||
// 请求参数
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 汇付ID
|
||||
reqParams.put("huifu_id", huifuId);
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis() + "");
|
||||
|
||||
// 联系人姓名
|
||||
reqParams.put("name", info.getIdcardName());
|
||||
// 联系人手机号
|
||||
reqParams.put("mobile", info.getContactPhone());
|
||||
// 联系人身份证号
|
||||
reqParams.put("id_card_number", info.getIdcardNo());
|
||||
|
||||
// 法人身份证人像面照片
|
||||
reqParams.put("identification_front_copy", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F02", info.getIdcard1Img(), mchApplyment.getIfCode()));
|
||||
// 法人身份证国徽面照片
|
||||
reqParams.put("identification_back_copy", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F03", info.getIdcard2Img(), mchApplyment.getIfCode()));
|
||||
|
||||
// 证书类型 【营业执照】
|
||||
reqParams.put("cert_type", "CERTIFICATE_TYPE_2392");
|
||||
// 证书编号
|
||||
reqParams.put("cert_number", info.getLicenseNo());
|
||||
// 证书照片
|
||||
reqParams.put("cert_copy", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F07", info.getLicenseImg(), mchApplyment.getIfCode()));
|
||||
// 小微经营类型
|
||||
reqParams.put("micro_biz_type", info.getMicroBizType());
|
||||
// 门店名称
|
||||
reqParams.put("store_name", info.getMchShortName());
|
||||
// 门店门头照
|
||||
reqParams.put("store_header_copy", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F49", info.getStoreOuterImg(), mchApplyment.getIfCode()));
|
||||
// 门店环境照
|
||||
reqParams.put("store_indoor_copy", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F50", info.getStoreInnerImg(), mchApplyment.getIfCode()));
|
||||
// 门店省市编码
|
||||
reqParams.put("store_address_code", info.getAreaCode().get(1));
|
||||
// 门店地址
|
||||
reqParams.put("store_address", info.getMchShortName());
|
||||
// 发送请求
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/merchant/busi/realname", mchApplyment.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
if (DgPayKit.STATE_SUCCESS.equals(code)) {
|
||||
// String channelOrderNo = resData.getString("applyment_id");
|
||||
// result.setChannelApplyNo(channelOrderNo);
|
||||
result.setState(MchApplyment.STATE_SUCCESS);
|
||||
} else {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo(code + "[" + resData.getString("resp_desc") + "]");
|
||||
log.error("{} 请求失败:code={}, msg={}", logPrefix, code, resData.getString("resp_desc"));
|
||||
return result;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo("[" + e.getMessage() + "]");
|
||||
log.error("{} 实名认证失败:", logPrefix, e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.lang.Pair;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.ChannelAccountCashoutRecord;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.cashout.CashoutRetMsg;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvsubMchParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.core.utils.DateKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractChannelAccountService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 提现接口: 斗拱
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2023/6/14 16:19
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DgpayChannelAccountService extends AbstractChannelAccountService {
|
||||
|
||||
@Autowired private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.DGPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<String, Long> queryBalanceAmount(MchAppConfigContext mchAppConfigContext, String ifCode) {
|
||||
String logPrefix = "斗拱商户余额查询";
|
||||
|
||||
DgpayIsvsubMchParams subMchParams = (DgpayIsvsubMchParams) configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), ifCode);
|
||||
if (subMchParams == null) {
|
||||
throw new BizException("斗拱商户余额查询,商户参数未配置");
|
||||
}
|
||||
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis());
|
||||
// 商户号
|
||||
reqParams.put("huifu_id", subMchParams.getHuifuId());
|
||||
|
||||
log.info(logPrefix);
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/trade/acctpayment/balance/query", ifCode);
|
||||
JSONObject jsonData = response.getJSONObject("data");
|
||||
|
||||
Long balanceAmt = 0L;
|
||||
// 响应成功
|
||||
if (DgPayKit.STATE_SUCCESS.equals(jsonData.getString("resp_code"))) {
|
||||
// 账户信息列表
|
||||
JSONArray infoList = jsonData.getJSONArray("acctInfo_list");
|
||||
for (int i = 0; i < infoList.size(); i++) {
|
||||
JSONObject infoJson = JSONObject.parseObject(infoList.get(i).toString());
|
||||
// 查询基本账户类型
|
||||
if ("01".equals(infoJson.getString("acct_type"))) {
|
||||
balanceAmt = Long.parseLong(AmountUtil.convertDollar2Cent(infoJson.getString("balance_amt")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Pair<>(subMchParams.getHuifuId(), balanceAmt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CashoutRetMsg cashout(ChannelAccountCashoutRecord cashoutRecord, MchAppConfigContext mchAppConfigContext, String ifCode) {
|
||||
String logPrefix = "斗拱商户提现";
|
||||
CashoutRetMsg cashoutRetMsg = new CashoutRetMsg();
|
||||
|
||||
DgpayIsvParams isvParams = (DgpayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment().getIsvNo(), ifCode);
|
||||
DgpayIsvsubMchParams subMchParams = (DgpayIsvsubMchParams) configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), ifCode);
|
||||
if (subMchParams == null) {
|
||||
throw new BizException("斗拱商户提现,商户参数未配置");
|
||||
}
|
||||
|
||||
try {
|
||||
if ("0".equals(isvParams.getMchSettManual())) {
|
||||
throw new BizException("斗拱商户提现,服务商未开启取现配置");
|
||||
}
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", cashoutRecord.getRid());
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 商户号
|
||||
reqParams.put("huifu_id", subMchParams.getHuifuId());
|
||||
// 到账类型
|
||||
reqParams.put("into_acct_date_type", isvParams.getMchSettManual());
|
||||
// 取现卡序列号
|
||||
reqParams.put("token_no", subMchParams.getTokenNo());
|
||||
// 取现金额
|
||||
reqParams.put("cash_amt", AmountUtil.convertCent2Dollar(cashoutRecord.getCashoutAmount()));
|
||||
// 异步通知地址
|
||||
reqParams.put("notify_url", getNotifyUrl());
|
||||
|
||||
log.info(logPrefix);
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/trade/settlement/enchashment", ifCode);
|
||||
JSONObject dataJSON = response.getJSONObject("data");
|
||||
|
||||
// 响应成功
|
||||
if (DgPayKit.STATE_SUCCESS.equals(dataJSON.getString("resp_code"))) {
|
||||
// 交易状态 S:成功 F:失败 P:处理中
|
||||
String transStat = dataJSON.getString("trans_stat");
|
||||
if (DgPayKit.STATE_SUCCESS_S.equals(transStat)) {
|
||||
cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
cashoutRetMsg.setChannelOrderId(dataJSON.getString("hf_seq_id")); // 渠道提现单号
|
||||
|
||||
}else if (DgPayKit.STATE_FAIL_F.equals(transStat)) {
|
||||
cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
cashoutRetMsg.setChannelErrCode(dataJSON.getString("resp_code"));
|
||||
cashoutRetMsg.setChannelErrMsg(dataJSON.getString("resp_desc"));
|
||||
|
||||
}else {
|
||||
cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
}
|
||||
}else {
|
||||
cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
cashoutRetMsg.setChannelErrMsg(dataJSON.getString("resp_desc"));
|
||||
}
|
||||
|
||||
return cashoutRetMsg;
|
||||
|
||||
} catch (Exception e) {
|
||||
cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
cashoutRetMsg.setChannelErrMsg(e.getMessage());
|
||||
return cashoutRetMsg;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CashoutRetMsg cashoutQuery(ChannelAccountCashoutRecord cashoutRecord, MchAppConfigContext mchAppConfigContext, String ifCode) {
|
||||
String logPrefix = "斗拱商户提现结果查询";
|
||||
CashoutRetMsg cashoutRetMsg = new CashoutRetMsg();
|
||||
|
||||
DgpayIsvsubMchParams subMchParams = (DgpayIsvsubMchParams) configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), ifCode);
|
||||
if (subMchParams == null) {
|
||||
throw new BizException("斗拱商户提现结果查询失败,商户参数未配置");
|
||||
}
|
||||
|
||||
try {
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 商户号
|
||||
reqParams.put("huifu_id", subMchParams.getHuifuId());
|
||||
// 原交易请求日期
|
||||
reqParams.put("org_req_date", DateUtil.format(cashoutRecord.getCreatedAt(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 原交易请求流水号
|
||||
reqParams.put("org_req_seq_id", cashoutRecord.getRid());
|
||||
|
||||
log.info(logPrefix);
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/trade/settlement/query", ifCode);
|
||||
|
||||
JSONObject dataJSON = response.getJSONObject("data");
|
||||
|
||||
// 响应成功
|
||||
if (DgPayKit.STATE_SUCCESS.equals(dataJSON.getString("resp_code"))) {
|
||||
// 交易状态 S:成功 F:失败 P:处理中
|
||||
String transStat = dataJSON.getString("trans_status");
|
||||
if (DgPayKit.STATE_SUCCESS_S.equals(transStat)) {
|
||||
cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
cashoutRetMsg.setChannelOrderId(dataJSON.getString("hf_seq_id")); // 渠道提现单号
|
||||
|
||||
}else if (DgPayKit.STATE_FAIL_F.equals(transStat)) {
|
||||
cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
cashoutRetMsg.setChannelErrCode(dataJSON.getString("resp_code"));
|
||||
cashoutRetMsg.setChannelErrMsg(dataJSON.getString("resp_desc"));
|
||||
|
||||
}else {
|
||||
cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
}
|
||||
}else {
|
||||
cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
cashoutRetMsg.setChannelErrMsg(dataJSON.getString("resp_desc"));
|
||||
}
|
||||
|
||||
return cashoutRetMsg;
|
||||
|
||||
} catch (Exception e) {
|
||||
cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
cashoutRetMsg.setChannelErrMsg(e.getMessage());
|
||||
return cashoutRetMsg;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.ChannelAccountCashoutRecord;
|
||||
import com.jeequan.jeepay.core.exception.ResponseException;
|
||||
import com.jeequan.jeepay.core.model.cashout.CashoutRetMsg;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractChannelCashoutNoticeService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 斗拱提现回调
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2023-06-14 07:15
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DgpayChannelCashoutNoticeService extends AbstractChannelCashoutNoticeService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.DGPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlRid) {
|
||||
|
||||
try {
|
||||
|
||||
// 回调参数body【回调参数顺序固定】
|
||||
JSONObject reqParamJSON = getReqParamJSON();
|
||||
log.info("【斗拱提现回调参数】{}", reqParamJSON);
|
||||
JSONObject respData = reqParamJSON.getJSONObject("resp_data");
|
||||
String rid = respData.getString("req_seq_id");
|
||||
log.info("【斗拱提现回调参数】{}", respData);
|
||||
return MutablePair.of(rid, reqParamJSON);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("error", e);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CashoutRetMsg doNotice(HttpServletRequest request, Object params, ChannelAccountCashoutRecord cashoutRecord, MchAppConfigContext mchAppConfigContext) {
|
||||
try {
|
||||
String logPrefix = "处理斗拱提现回调";
|
||||
|
||||
CashoutRetMsg cashoutRetMsg = new CashoutRetMsg();
|
||||
|
||||
JSONObject jsonParams = (JSONObject) params;
|
||||
log.info("{}参数:{}", logPrefix, jsonParams);
|
||||
|
||||
// 业务失败
|
||||
if (!"10000".equals(jsonParams.getString("resp_code"))) {
|
||||
log.error("{} 业务失败,原因:{}", logPrefix, jsonParams.getString("resp_desc"));
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
|
||||
String respDataStr = jsonParams.getString("resp_data");
|
||||
JSONObject respDataJSON = JSONObject.parseObject(respDataStr);
|
||||
String sign = jsonParams.getString("sign");
|
||||
|
||||
// 交易状态 S:成功 F:失败 P:处理中
|
||||
String transStat = respDataJSON.getString("trans_status");
|
||||
if (DgPayKit.STATE_SUCCESS_S.equals(transStat)) {
|
||||
cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
cashoutRetMsg.setChannelOrderId(respDataJSON.getString("hf_seq_id")); // 渠道提现单号
|
||||
|
||||
}else if (DgPayKit.STATE_FAIL_F.equals(transStat)) {
|
||||
cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
cashoutRetMsg.setChannelErrCode(respDataJSON.getString("sub_resp_code"));
|
||||
cashoutRetMsg.setChannelErrMsg(respDataJSON.getString("sub_resp_desc"));
|
||||
|
||||
}else {
|
||||
cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
}
|
||||
|
||||
// 返回上游内容
|
||||
cashoutRetMsg.setResponseEntity(textResp("SUCCESS"));
|
||||
|
||||
// 校验提现回调
|
||||
boolean verifyResult = verifyParams(respDataStr, cashoutRecord, mchAppConfigContext, sign);
|
||||
// 验证参数失败
|
||||
if(!verifyResult){
|
||||
log.info("{}验证提现通知数据或签名失败", logPrefix);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
|
||||
cashoutRetMsg.setChannelOrderId(jsonParams.getString("acquireOrderNo"));
|
||||
cashoutRetMsg.setBankName(jsonParams.getString("bankName"));
|
||||
cashoutRetMsg.setBankAccount(jsonParams.getString("bankAccount"));
|
||||
cashoutRetMsg.setBankAccountName(jsonParams.getString("bankAccountName"));
|
||||
|
||||
return cashoutRetMsg;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("error", e);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证斗拱提现通知参数
|
||||
* @return
|
||||
*/
|
||||
public boolean verifyParams(String respDataStr, ChannelAccountCashoutRecord cashoutRecord, MchAppConfigContext mchAppConfigContext, String sign) {
|
||||
// 提现金额
|
||||
String txnAmt = JSONObject.parseObject(respDataStr).getString("cash_amt");
|
||||
if (StringUtils.isEmpty(txnAmt)) {
|
||||
log.info("金额参数为空 [txnAmt] :{}", txnAmt);
|
||||
return false;
|
||||
}
|
||||
// 核对金额
|
||||
long dbPayAmt = cashoutRecord.getCashoutAmount();
|
||||
if (dbPayAmt != AmountUtil.convertDollar2CentLong(txnAmt)) {
|
||||
log.info("订单金额与参数金额不符。 dbPayAmt={}, txnAmt={}, rid={}", dbPayAmt, txnAmt, cashoutRecord.getRid());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 公钥参数
|
||||
DgpayIsvParams isvParams = (DgpayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment().getIsvNo(), cashoutRecord.getIfCode());
|
||||
|
||||
// 验证签名
|
||||
boolean verifyResult = DgPayKit.verify(respDataStr, isvParams.getRsaPublicKey(), sign);
|
||||
if(!verifyResult){
|
||||
log.info("【斗拱提现回调】 验签失败! 回调参数:respDataStr = {}", respDataStr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.ResponseException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractChannelNoticeService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 斗拱 回调接口实现类
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/6/13 15:58
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DgpayChannelNoticeService extends AbstractChannelNoticeService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.DGPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlOrderId, NoticeTypeEnum noticeTypeEnum) {
|
||||
|
||||
try {
|
||||
// 回调参数body【回调参数顺序固定】
|
||||
JSONObject reqParamJSON = getReqParamJSON();
|
||||
JSONObject dataJson = reqParamJSON.getJSONObject("resp_data");
|
||||
String payOrderId = dataJson.getString("req_seq_id");
|
||||
return MutablePair.of(payOrderId, reqParamJSON);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("error", e);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg doNotice(HttpServletRequest request, Object params, PayOrder payOrder, MchAppConfigContext mchAppConfigContext, NoticeTypeEnum noticeTypeEnum) {
|
||||
try {
|
||||
String logPrefix = "【处理[斗拱]支付回调】";
|
||||
JSONObject jsonParams = (JSONObject) params;
|
||||
String dataJson = jsonParams.getString("resp_data");
|
||||
String sign = jsonParams.getString("sign");
|
||||
log.info("{} 回调参数, dataJson:{}, sign:{}", logPrefix, dataJson, sign);
|
||||
|
||||
// 公钥参数
|
||||
DgpayIsvParams isvParams = (DgpayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment().getIsvNo(), payOrder.getIfCode());
|
||||
|
||||
// 验证签名
|
||||
boolean verifyResult = DgPayKit.verify(dataJson, isvParams.getRsaPublicKey(), sign);
|
||||
|
||||
//验签失败
|
||||
if(!verifyResult){
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
|
||||
//验签成功后判断上游订单状态
|
||||
ResponseEntity okResponse = textResp("SUCCESS");
|
||||
|
||||
ChannelRetMsg result = new ChannelRetMsg();
|
||||
|
||||
result.setChannelBizData(jsonParams);
|
||||
// 默认支付中
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
// 获取请求参数
|
||||
JSONObject respData = jsonParams.getJSONObject("resp_data");
|
||||
if(DgPayKit.STATE_SUCCESS_S.equals(respData.getString("trans_stat"))){
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
|
||||
}else if(DgPayKit.STATE_FAIL_F.equals(respData.getString("trans_stat"))){
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
// 交易状态失败存储
|
||||
DgPayKit.channelMsgError(respData, result);
|
||||
}
|
||||
/***
|
||||
* D-借记卡,C-贷记卡,0-其他;示例值:D
|
||||
*/
|
||||
String debit_type = respData.getString("debit_type");
|
||||
if(StringUtils.isEmpty(debit_type) || "0".equals(debit_type)){
|
||||
result.setDrType(CS.DrType.OTHER.getType());
|
||||
}else if("D".equals(debit_type)){
|
||||
result.setDrType(CS.DrType.DEBIT.getType());
|
||||
}else if("C".equals(debit_type)){
|
||||
result.setDrType(CS.DrType.CREDIT.getType());
|
||||
}else{
|
||||
result.setDrType(CS.DrType.OTHER.getType());
|
||||
}
|
||||
result.setResponseEntity(okResponse);
|
||||
result.setChannelOrderId(respData.getString("hf_seq_id"));
|
||||
result.setPlatformOrderNo(respData.getString("out_trans_id"));
|
||||
result.setPlatformMchOrderNo(respData.getString("party_order_id"));
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("error", e);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.exception.ResponseException;
|
||||
import com.jeequan.jeepay.core.model.autopos.ChannelOrderAcceptParams;
|
||||
import com.jeequan.jeepay.core.model.autopos.ChannelOrderAcceptRetMsg;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.IsvParams;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.core.utils.JsonKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractChannelOrderAcceptService;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.utils.MD5Utils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 斗拱智能POS回调
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2021-06-07 07:15
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DgpayChannelOrderAcceptService extends AbstractChannelOrderAcceptService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.DGPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelOrderAcceptParams parseParams(HttpServletRequest request, IsvParams isvParams) {
|
||||
|
||||
JSONObject params = getReqParamJSON();
|
||||
|
||||
// 获取事件类型
|
||||
String eventDefineNo = params.getString("event_define_no");
|
||||
|
||||
String tradeType = ""; // 交易类型 收款-PAYMENT 退款-REFUND
|
||||
if (DgPayKit.POS_PAY_EVENT.contains(eventDefineNo)) {
|
||||
tradeType = ChannelOrderAcceptParams.TRADE_TYPE_PAYMENT;
|
||||
} else if (DgPayKit.POS_REFUND_EVENT.contains(eventDefineNo)) {
|
||||
tradeType = ChannelOrderAcceptParams.TRADE_TYPE_REFUND;
|
||||
}
|
||||
|
||||
log.info("斗拱智能POS【订单通知模式】通知参数:tradeType={},params={}", tradeType, params.toJSONString());
|
||||
return ChannelOrderAcceptParams.buildAutoPosParams(tradeType, params.getString("devs_id"), params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelOrderAcceptRetMsg payNotice(HttpServletRequest request, Object params, MchAppConfigContext mchAppConfigContext, String ifCode) throws Exception {
|
||||
|
||||
String logPrefix = "处理斗拱智能POS【订单通知模式】支付通知";
|
||||
|
||||
ChannelOrderAcceptRetMsg result = new ChannelOrderAcceptRetMsg();
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
// 获取请求参数
|
||||
JSONObject jsonParams = (JSONObject) params;
|
||||
|
||||
// 验签
|
||||
boolean verifyResult = validateSign(jsonParams, mchAppConfigContext, request.getParameterMap().get("sign")[0], ifCode);
|
||||
if(!verifyResult){
|
||||
log.info("{}验证通知数据及签名失败", logPrefix);
|
||||
throw ResponseException.buildText4HttpStatus500("FAIL");
|
||||
}
|
||||
|
||||
// 支付状态
|
||||
String status = jsonParams.getString("trans_stat");
|
||||
// 支付成功
|
||||
if (StringUtils.equals(DgPayKit.STATE_SUCCESS_S, status)) {
|
||||
result.setResponseEntity(textResp("SUCCESS")); // 通知上游处理成功
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
|
||||
JSONObject transOrderInfo = jsonParams.getJSONObject("trans_order_info");
|
||||
result.setChannelOrderId(transOrderInfo.getString("mer_ord_id")); // 渠道订单号,必填
|
||||
result.setChannelBizData(JsonKit.newJson("reqSeqId", transOrderInfo.getString("req_seq_id"))); // 分账使用 渠道特殊参数
|
||||
|
||||
result.setChannelAmount(AmountUtil.convertDollar2CentLong(jsonParams.getString("trans_amt"))); // 订单金额,单位分,必填
|
||||
result.setBizOrderId(transOrderInfo.getString("mer_ord_id"));
|
||||
result.setChannelWayCode(CS.PAY_WAY_CODE.AUTO_POS); // 支付方式,必填
|
||||
result.setChannelWayCodeType(covertWayCodeType(jsonParams.getString("event_define_no"))); // 支付方式类型,必填
|
||||
result.setChannelDivisionMode(jsonParams.getByte("is_delay_acct"));
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ChannelOrderAcceptRetMsg refundNotice(HttpServletRequest request, Object params, MchAppConfigContext mchAppConfigContext, String ifCode) {
|
||||
try {
|
||||
String logPrefix = "处理斗拱智能POS【订单通知模式】退款通知";
|
||||
|
||||
ChannelOrderAcceptRetMsg result = new ChannelOrderAcceptRetMsg();
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
// 获取请求参数
|
||||
JSONObject jsonParams = (JSONObject) params;
|
||||
|
||||
// 验签
|
||||
boolean verifyResult = validateSign(jsonParams, mchAppConfigContext, request.getParameterMap().get("sign")[0], ifCode);
|
||||
if(!verifyResult){
|
||||
log.info("{}验证通知数据及签名失败", logPrefix);
|
||||
throw ResponseException.buildText4HttpStatus500("FAIL");
|
||||
}
|
||||
|
||||
// 退款状态
|
||||
String status = jsonParams.getString("trans_stat");
|
||||
// 退款成功
|
||||
if (StringUtils.equals(DgPayKit.STATE_SUCCESS_S, status)) {
|
||||
result.setResponseEntity(textResp("SUCCESS")); // 通知上游处理成功
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
result.setChannelOrderId(jsonParams.getString("mer_ord_id")); // 渠道订单号,必填
|
||||
|
||||
result.setChannelAmount(AmountUtil.convertDollar2CentLong(jsonParams.getString("ord_amt"))); // 订单金额,单位分,必填
|
||||
result.setBizOrderId(jsonParams.getString("mer_ord_id"));
|
||||
result.setChannelPayOrderId(jsonParams.getString("org_term_ord_id")); // 原渠道订单号(和支付订单渠道订单号一致),退款必填
|
||||
result.setChannelDivisionRefundMode((byte) 1);
|
||||
}
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("error", e);
|
||||
throw ResponseException.buildText4HttpStatus500("FAIL");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验签
|
||||
* @return
|
||||
*/
|
||||
public boolean validateSign(JSONObject jsonParams, MchAppConfigContext mchAppConfigContext, String sign, String ifCode) throws Exception {
|
||||
|
||||
DgpayIsvParams isvParams =
|
||||
(DgpayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment().getIsvNo(), ifCode);
|
||||
|
||||
return MD5Utils.verifySign(jsonParams.toJSONString(), isvParams.getWebhookPrivateKey(), sign);
|
||||
}
|
||||
|
||||
private String covertWayCodeType(String eventDefineNo) {
|
||||
|
||||
switch (eventDefineNo) {
|
||||
case "pay.ali_scaned": return CS.PAY_WAY_CODE_TYPE.ALIPAY;
|
||||
case "pay.wx_scaned": return CS.PAY_WAY_CODE_TYPE.WECHAT;
|
||||
case "pay.union_scaned":
|
||||
case "pay.card_consume.pos":
|
||||
case "pay.digit_scaned":
|
||||
return CS.PAY_WAY_CODE_TYPE.UNIONPAY;
|
||||
default: return CS.PAY_WAY_CODE_TYPE.OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.RefundOrder;
|
||||
import com.jeequan.jeepay.core.exception.ResponseException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.params.yspay.YspayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractChannelRefundNoticeService;
|
||||
import com.jeequan.jeepay.thirdparty.channel.yspay.utils.SignRsaUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.yspay.utils.SignSmUtil;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 斗拱退款回调接口实现类
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2021/12/24 11:31
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DgpayChannelRefundNoticeService extends AbstractChannelRefundNoticeService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.DGPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlOrderId, NoticeTypeEnum noticeTypeEnum) {
|
||||
try {
|
||||
// 回调参数body【回调参数顺序固定】
|
||||
JSONObject reqParamJSON = getReqParamJSON();
|
||||
JSONObject dataJson = reqParamJSON.getJSONObject("resp_data");
|
||||
String payOrderId = dataJson.getString("req_seq_id");
|
||||
return MutablePair.of(payOrderId, reqParamJSON);
|
||||
} catch (Exception e) {
|
||||
log.error("error", e);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg doNotice(HttpServletRequest request, Object params, RefundOrder refundOrder, MchAppConfigContext mchAppConfigContext, NoticeTypeEnum noticeTypeEnum) {
|
||||
try {
|
||||
// 获取请求参数
|
||||
JSONObject jsonParams = (JSONObject) params;
|
||||
String dataJson = jsonParams.getString("resp_data");
|
||||
String sign = jsonParams.getString("sign");
|
||||
log.info("【斗拱】退款回调参数:{} ", jsonParams);
|
||||
// 公钥参数
|
||||
DgpayIsvParams isvParams = (DgpayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment());
|
||||
// 验证签名
|
||||
boolean verifyResult = DgPayKit.verify(dataJson, isvParams.getRsaPublicKey(), sign);
|
||||
//验签失败
|
||||
if(!verifyResult){
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
//验签成功后判断上游订单状态
|
||||
ResponseEntity okResponse = textResp("SUCCESS");
|
||||
ChannelRetMsg result = new ChannelRetMsg();
|
||||
// 默认退款中
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
// 获取请求参数
|
||||
JSONObject respData = jsonParams.getJSONObject("resp_data");
|
||||
if(DgPayKit.STATE_SUCCESS_S.equals(respData.getString("trans_stat"))){
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
|
||||
}else if(DgPayKit.STATE_FAIL_F.equals(respData.getString("trans_stat"))){
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
// 交易状态失败存储
|
||||
DgPayKit.channelMsgError(respData, result);
|
||||
}
|
||||
result.setResponseEntity(okResponse);
|
||||
result.setChannelOrderId(respData.getString("hf_seq_id"));
|
||||
result.setPlatformMchOrderNo(respData.getString("party_order_id"));
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("error", e);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 验证银盛退款通知参数
|
||||
* @return
|
||||
*/
|
||||
public boolean verifyParams(JSONObject jsonParams, MchAppConfigContext mchAppConfigContext) {
|
||||
try {
|
||||
log.info("【银盛】退款回调参数: jsonParams:{}", jsonParams);
|
||||
String sign = jsonParams.getString("sign");
|
||||
Map<String, String> paramsMap = jsonParams.toJavaObject(Map.class);
|
||||
if (StringUtils.isEmpty(sign)) {
|
||||
log.info("验签参数为空:sign:{}", sign);
|
||||
return false;
|
||||
}
|
||||
// 校验支付回调
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
YspayIsvParams isvParams = (YspayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment());
|
||||
// 证书地址
|
||||
ChannelCertConfigKitBean channelCertConfigKitBean = SpringBeansUtil.getBean(ChannelCertConfigKitBean.class);
|
||||
String certFilePath = channelCertConfigKitBean.getCertFilePath(isvParams.getPublicKeyFile());
|
||||
boolean verifyResult = false;
|
||||
if ("RSA".equals(isvParams.getSignType())) {
|
||||
FileInputStream fileInputStream = new FileInputStream(channelCertConfigKitBean.getCertFile(isvParams.getPublicKeyFile()));
|
||||
verifyResult = SignRsaUtil.asynVerifyYsRsa(fileInputStream, paramsMap);
|
||||
}else if ("SM".equals(isvParams.getSignType())){
|
||||
verifyResult = SignSmUtil.asynVerifyYsSm(certFilePath, paramsMap);
|
||||
}else {
|
||||
log.error("未识别的签名类型");
|
||||
}
|
||||
//验签失败
|
||||
if(!verifyResult) {
|
||||
log.info("【银盛】退款回调验签失败! 回调参数:parameter = {} ", jsonParams);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IChannelUserService;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvsubMchParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelUserInfoMsg;
|
||||
import com.jeequan.jeepay.core.utils.DateKit;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 获取银联userId实现类
|
||||
*
|
||||
* @author jmdhapy
|
||||
*
|
||||
* @date 2022/3/17 16:51
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DgpayChannelUserService implements IChannelUserService {
|
||||
|
||||
@Autowired protected ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.DGPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelUserInfoMsg buildUserRedirectUrl(String callbackUrlEncode, MchAppConfigContext mchAppConfigContext) {
|
||||
|
||||
//云闪付返回地址
|
||||
String ysfRedirectUrl = String.format("https://qr.95516.com/qrcGtwWeb-web/api/userAuth?version=1.0.0&redirectUrl=%s", callbackUrlEncode);
|
||||
log.info("【斗拱】ysfRedirectUrl={}", ysfRedirectUrl);
|
||||
return ChannelUserInfoMsg.gen(ysfRedirectUrl, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getChannelUserId(String pageType, JSONObject reqParams, MchAppConfigContext mchAppConfigContext, String ifCode) {
|
||||
String logPrefix = "【斗拱获取银联行业码用户ID】";
|
||||
try {
|
||||
String userAuthCode = reqParams.getString("userAuthCode"); //云闪付 userAuthCode
|
||||
String appUpIdentifier = reqParams.getString("appUpIdentifier");
|
||||
log.info("{} userAuthCode={}, appUpIdentifier={}", logPrefix, userAuthCode, appUpIdentifier);
|
||||
DgpayIsvsubMchParams mchParams = (DgpayIsvsubMchParams)configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), ifCode);
|
||||
|
||||
JSONObject reqJson = new JSONObject();
|
||||
// 交易流水号
|
||||
reqJson.put("req_seq_id", DateKit.currentTimeMillis()+"");
|
||||
// 请求日期
|
||||
reqJson.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 汇付商户号
|
||||
reqJson.put("huifu_id", mchParams.getHuifuId());
|
||||
// 用户授权码
|
||||
reqJson.put("auth_code", userAuthCode);
|
||||
// 银联支付标识
|
||||
reqJson.put("app_up_identifier", appUpIdentifier);
|
||||
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqJson, "/trade/payment/usermark2/query", ifCode);
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
String userId = "";
|
||||
if (DgPayKit.STATE_SUCCESS.equals(code)) {
|
||||
userId = resData.getString("user_id");
|
||||
}else {
|
||||
log.error("请求失败:code={}, sub_msg={}", code, response.getString("resp_desc"));
|
||||
return userId;
|
||||
}
|
||||
return userId;
|
||||
} catch (Exception e) {
|
||||
log.error("{}异常", logPrefix, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,477 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.date.DateField;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.*;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.applyment.DgpayApplymentInfo;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvsubMchParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.core.utils.DateKit;
|
||||
import com.jeequan.jeepay.core.utils.JsonKit;
|
||||
import com.jeequan.jeepay.core.utils.SeqKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractDivisionService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账接口
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/8/1 15:39
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DgpayDivisionService extends AbstractDivisionService {
|
||||
|
||||
@Autowired private ConfigContextQueryService configContextQueryService;
|
||||
@Autowired private DgpayMchApplymentService dgpayMchApplymentService;
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.DGPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupport() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg bind(MchDivisionReceiver mchDivisionReceiver, MchAppConfigContext mchAppConfigContext) {
|
||||
|
||||
try {
|
||||
|
||||
String logPrefix = "[斗拱添加分账]";
|
||||
// 新创建的分账接收者的mchId
|
||||
String newDivisionReceiverSubMchId = null;
|
||||
|
||||
// 实际使用ifCode,用于查询支付参数
|
||||
String ifCode = mchDivisionReceiver.getIfCode();
|
||||
|
||||
// 当channelExtInfo 传入: {} , 说明是subMchId直接绑定模式
|
||||
JSONObject channelExtInfoJOSN = JSON.parseObject(mchDivisionReceiver.getChannelExtInfo());
|
||||
if(channelExtInfoJOSN.isEmpty()){
|
||||
throw new BizException("分账配置信息错误");
|
||||
}
|
||||
newDivisionReceiverSubMchId = mchDivisionReceiver.getAccNo();
|
||||
|
||||
Boolean isHasAccount = (Boolean) channelExtInfoJOSN.getOrDefault("isHasAccount", false);
|
||||
|
||||
// 新增的分账接收方:调起进件接口,并需要返回一个 subMchId
|
||||
if(!isHasAccount){
|
||||
// 1.基本信息开户
|
||||
MchApplyment mchApplyment = new MchApplyment(); // 构造进件相关请求参数
|
||||
mchApplyment.setApplyId(SeqKit.genMchApplyNo());
|
||||
mchApplyment.setIsvNo(mchAppConfigContext.getMchApplyment().getIsvNo());
|
||||
mchApplyment.setApplyDetailInfo(mchDivisionReceiver.getChannelExtInfo());
|
||||
mchApplyment.setIfCode(ifCode);
|
||||
// 进件参数
|
||||
JSONObject reqParams = dgpayMchApplymentService.getApplymentParams(mchApplyment);
|
||||
// 开户参数
|
||||
dgpayMchApplymentService.setAccountInfo(mchApplyment, reqParams);
|
||||
|
||||
// 银行卡参数
|
||||
JSONObject cardInfo = reqParams.getJSONObject("card_info");
|
||||
reqParams.remove("card_info");
|
||||
|
||||
DgpayApplymentInfo applymentInfo = JSONObject.parseObject(mchApplyment.getApplyDetailInfo(), DgpayApplymentInfo.class);
|
||||
|
||||
JSONArray fileArr = new JSONArray();
|
||||
// 门头照
|
||||
String storeOuterImg = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F49", applymentInfo.getStoreOuterImg(), ifCode);
|
||||
if (StringUtils.isNotEmpty(storeOuterImg)) {
|
||||
JSONObject json = JsonKit.newJson("file_type", "F49");
|
||||
json.put("file_id", storeOuterImg);
|
||||
fileArr.add(json);
|
||||
}
|
||||
// 内景照
|
||||
String storeInnerImg = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F50", applymentInfo.getStoreInnerImg(), ifCode);
|
||||
if (StringUtils.isNotEmpty(storeInnerImg)) {
|
||||
JSONObject json = JsonKit.newJson("file_type", "F50");
|
||||
json.put("file_id", storeInnerImg);
|
||||
fileArr.add(json);
|
||||
}
|
||||
// 收银台照
|
||||
String storeCashierImg = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F105", applymentInfo.getStoreCashierImg(), ifCode);
|
||||
if (StringUtils.isNotEmpty(storeCashierImg)) {
|
||||
JSONObject json = JsonKit.newJson("file_type", "F105");
|
||||
json.put("file_id", storeCashierImg);
|
||||
fileArr.add(json);
|
||||
}
|
||||
// 法人身份证人像面照片
|
||||
String idcard1Img = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F02", applymentInfo.getIdcard1Img(), ifCode);
|
||||
if (StringUtils.isNotEmpty(idcard1Img)) {
|
||||
JSONObject json = JsonKit.newJson("file_type", "F02");
|
||||
json.put("file_id", idcard1Img);
|
||||
fileArr.add(json);
|
||||
}
|
||||
// 法人身份证国徽面照片
|
||||
String idcard2Img = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F03", applymentInfo.getIdcard2Img(), ifCode);
|
||||
if (StringUtils.isNotEmpty(idcard2Img)) {
|
||||
JSONObject json = JsonKit.newJson("file_type", "F03");
|
||||
json.put("file_id", idcard2Img);
|
||||
fileArr.add(json);
|
||||
}
|
||||
// 营业执照
|
||||
String licenseImg = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F07", applymentInfo.getLicenseImg(), ifCode);
|
||||
if (StringUtils.isNotEmpty(licenseImg)) {
|
||||
JSONObject json = JsonKit.newJson("file_type", "F07");
|
||||
json.put("file_id", licenseImg);
|
||||
fileArr.add(json);
|
||||
}
|
||||
// 商务协议
|
||||
String baPicImg = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F116", applymentInfo.getBankPic(), ifCode);
|
||||
if (StringUtils.isNotEmpty(baPicImg)) {
|
||||
JSONObject json = JsonKit.newJson("file_type", "F116");
|
||||
json.put("file_id", baPicImg);
|
||||
fileArr.add(json);
|
||||
}
|
||||
|
||||
reqParams.put("file_list", fileArr.toJSONString());
|
||||
|
||||
// 步骤1 请求地址 企业开户和个人开户地址
|
||||
String step1Url = applymentInfo.getMerchantType() == 1?"/user/basicdata/indv":"/user/basicdata/ent";
|
||||
// 发起开户请求
|
||||
JSONObject responseStep1 = DgPayKit.request(mchAppConfigContext, reqParams, step1Url, ifCode);
|
||||
JSONObject dataJson1 = responseStep1.getJSONObject("data");
|
||||
// 响应失败
|
||||
if (!DgPayKit.STATE_SUCCESS.equals(dataJson1.getString("resp_code"))) {
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrCode(dataJson1.getString("resp_code"));
|
||||
channelRetMsg.setChannelErrMsg(dataJson1.getString("resp_desc"));
|
||||
return channelRetMsg;
|
||||
}
|
||||
// 获取汇付ID号
|
||||
String huifuId = dataJson1.getString("huifu_id");
|
||||
|
||||
// 2.业务入驻
|
||||
DgpayIsvsubMchParams mchParams = (DgpayIsvsubMchParams)configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), ifCode);
|
||||
// 汇付ID
|
||||
reqParams.put("huifu_id", huifuId);
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", SeqKit.genMchApplyNo());
|
||||
// 商户编号
|
||||
reqParams.put("upper_huifu_id", mchParams.getHuifuId());
|
||||
// 延迟入账开关
|
||||
reqParams.put("delay_flag", "Y");
|
||||
// 银行卡参数
|
||||
reqParams.put("card_info", cardInfo);
|
||||
reqParams.remove("noMchId");
|
||||
// 步骤2 请求地址 用户业务入驻
|
||||
String step2Url = "/user/busi/open";
|
||||
// 发起开户请求
|
||||
JSONObject responseStep2 = DgPayKit.request(mchAppConfigContext, reqParams, step2Url, ifCode);
|
||||
JSONObject dataJson2 = responseStep2.getJSONObject("data");
|
||||
// 响应失败
|
||||
if (!DgPayKit.STATE_SUCCESS.equals(dataJson2.getString("resp_code"))) {
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
// 状态失败
|
||||
DgPayKit.channelMsgError(dataJson2, channelRetMsg);
|
||||
return channelRetMsg;
|
||||
}
|
||||
JSONObject paramsJson = new JSONObject();
|
||||
String tokenNo = dataJson2.getString("token_no");
|
||||
paramsJson.put("tokenNo", tokenNo);
|
||||
paramsJson.put("huifuId", huifuId);
|
||||
newDivisionReceiverSubMchId = paramsJson.toJSONString();
|
||||
}else {
|
||||
JSONObject paramsJson = JsonKit.newJson("huifuId", newDivisionReceiverSubMchId);
|
||||
// 取现卡序列号
|
||||
if (StringUtils.isNotEmpty(mchDivisionReceiver.getChannelExtInfo())) {
|
||||
String tokenNo = channelExtInfoJOSN.getString("tokenNo");
|
||||
paramsJson.put("tokenNo", tokenNo);
|
||||
}
|
||||
|
||||
newDivisionReceiverSubMchId = paramsJson.toJSONString();
|
||||
}
|
||||
|
||||
//在channelAttach数据中,写入 渠道用户编号
|
||||
return ChannelRetMsg.confirmSuccess(null).setChannelAttach(newDivisionReceiverSubMchId);
|
||||
} catch (ChannelException e) {
|
||||
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrCode(e.getChannelRetMsg().getChannelErrCode());
|
||||
channelRetMsg.setChannelErrMsg(e.getChannelRetMsg().getChannelErrMsg());
|
||||
return channelRetMsg;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("添加斗拱分账异常", e);
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrMsg(e.getMessage());
|
||||
return channelRetMsg;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg singleDivision(PayOrder payOrder, List<PayOrderDivisionRecord> recordList, MchAppConfigContext mchAppConfigContext) {
|
||||
|
||||
try {
|
||||
// 分账批次号
|
||||
String batchOrderId = recordList.get(0).getBatchOrderId();
|
||||
|
||||
if(recordList.isEmpty()){ // 当无分账用户时,直接响应成功即可。
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}
|
||||
|
||||
String logPrefix = "【斗拱分账】";
|
||||
|
||||
DgpayIsvsubMchParams isvsubMchParams = (DgpayIsvsubMchParams) configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), payOrder.getIfCode());
|
||||
String mchId = isvsubMchParams.getHuifuId();
|
||||
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", batchOrderId);
|
||||
// 商户号
|
||||
reqParams.put("huifu_id", mchId);
|
||||
|
||||
String orgReqSeqId = payOrder.getPayOrderId();
|
||||
if (StringUtils.equals(CS.PAY_WAY_CODE.AUTO_POS, payOrder.getWayCode())) {
|
||||
orgReqSeqId = payOrder.getChannelOrderNo();
|
||||
|
||||
if (payOrder.getChannelBizData() != null && StringUtils.isNotBlank(payOrder.getChannelBizData())) {
|
||||
JSONObject channelBizData = JSONObject.parseObject(payOrder.getChannelBizData());
|
||||
|
||||
if (StringUtils.isNotBlank(channelBizData.getString("reqSeqId"))) {
|
||||
orgReqSeqId = channelBizData.getString("reqSeqId");
|
||||
}
|
||||
}
|
||||
}
|
||||
// 原交易请求流水号
|
||||
reqParams.put("org_req_seq_id", orgReqSeqId);
|
||||
// 下单日期
|
||||
reqParams.put("org_req_date", DateUtil.format(payOrder.getSuccessTime(), DatePattern.PURE_DATE_PATTERN));
|
||||
|
||||
JSONArray receivers = new JSONArray();
|
||||
for (int i = 0; i < recordList.size(); i++) {
|
||||
PayOrderDivisionRecord record = recordList.get(i);
|
||||
if(record.getCalDivisionAmount() <= 0){ //金额为 0 不参与分账处理
|
||||
continue;
|
||||
}
|
||||
if(StringUtils.isEmpty(record.getChannelAccNo())){ // 判断是否都包含渠道号码
|
||||
throw new BizException(record.getAccName() + "账号没有分账渠道号, 本次分账失败");
|
||||
}
|
||||
|
||||
JSONObject paramsJson = JSONObject.parseObject(record.getChannelAccNo());
|
||||
JSONObject receiver = new JSONObject();
|
||||
receiver.put("huifu_id", paramsJson.getString("huifuId"));
|
||||
receiver.put("div_amt", AmountUtil.convertCent2Dollar(record.getCalDivisionAmount()));
|
||||
receivers.add(receiver);
|
||||
}
|
||||
|
||||
if(receivers.isEmpty()){
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}
|
||||
|
||||
// 分账对象
|
||||
JSONObject receiverJson = new JSONObject();
|
||||
receiverJson.put("acct_infos", receivers);
|
||||
reqParams.put("acct_split_bunch", receiverJson.toJSONString());
|
||||
|
||||
log.info("{}分账处理分账接收方", logPrefix);
|
||||
// 发起分账请求
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/trade/payment/delaytrans/confirm", payOrder.getIfCode());
|
||||
JSONObject dataJson = response.getJSONObject("data");
|
||||
// 响应失败
|
||||
if (!DgPayKit.STATE_SUCCESS.equals(dataJson.getString("resp_code"))) {
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
// 状态失败
|
||||
DgPayKit.channelMsgError(dataJson, channelRetMsg);
|
||||
return channelRetMsg;
|
||||
}
|
||||
|
||||
// 业务处理成功, 响应成功 交易状态为成功
|
||||
if(DgPayKit.STATE_SUCCESS.equals(dataJson.getString("resp_code")) && "S".equals(dataJson.getString("trans_stat"))) {
|
||||
|
||||
return ChannelRetMsg.confirmSuccess(dataJson.getString("req_seq_id"));
|
||||
}
|
||||
|
||||
// 订单处理中: 需要延迟到第二天5点进行结算
|
||||
if("P".equals(dataJson.getString("trans_stat"))){
|
||||
|
||||
// 第二天的5点钟
|
||||
Date nextDay5 = DateUtil.offset(DateKit.getBegin(DateUtil.offsetDay(new Date(), 1)), DateField.HOUR, 5);
|
||||
|
||||
// 触发MQ的时间, 单位: 秒
|
||||
Long delayTime = (nextDay5.getTime() - DateKit.currentTimeMillis()) / 1000;
|
||||
|
||||
return ChannelRetMsg.unknown().setChannelAttach(JsonKit.newJson("mqDelayTime", delayTime).toJSONString());
|
||||
|
||||
}else{ //其他情况认为: 失败
|
||||
return ChannelRetMsg.confirmFail().setChannelErrCode(dataJson.getString("resp_code")).setChannelErrMsg(dataJson.getString("resp_desc"));
|
||||
}
|
||||
|
||||
} catch (ChannelException e) {
|
||||
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrCode(e.getChannelRetMsg().getChannelErrCode());
|
||||
channelRetMsg.setChannelErrMsg(e.getChannelRetMsg().getChannelErrMsg());
|
||||
return channelRetMsg;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("斗拱分账异常", e);
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
channelRetMsg.setChannelErrMsg(e.getMessage());
|
||||
return channelRetMsg;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg divisionRefund(PayOrderDivisionRecord payOrderDivisionRecord, PayOrderDivisionRefundRecord payOrderDivisionRefundRecord, RefundOrder refundOrder, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) {
|
||||
String logPrefix = "【斗拱分账回退】";
|
||||
|
||||
try {
|
||||
// 防止接口限流
|
||||
Thread.sleep(1000);
|
||||
|
||||
DgpayIsvsubMchParams isvsubMchParams = (DgpayIsvsubMchParams) configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), payOrderDivisionRecord.getIfCode());
|
||||
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", payOrderDivisionRefundRecord.getDivisionRefundId());
|
||||
// 商户号
|
||||
reqParams.put("huifu_id", isvsubMchParams.getHuifuId());
|
||||
// 原交易请求日期
|
||||
reqParams.put("org_req_date", DateUtil.format(payOrderDivisionRecord.getCreatedAt(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 原交易请求流水号
|
||||
reqParams.put("org_req_seq_id", payOrderDivisionRecord.getChannelBatchOrderId());
|
||||
JSONObject paramsJson = JSONObject.parseObject(payOrderDivisionRecord.getChannelAccNo());
|
||||
JSONArray refundArr = new JSONArray();
|
||||
JSONObject refundJson = new JSONObject();
|
||||
refundJson.put("huifu_id", paramsJson.getString("huifuId"));
|
||||
refundJson.put("div_amt", AmountUtil.convertCent2Dollar(payOrderDivisionRefundRecord.getDivisionRefundAmount()));
|
||||
refundArr.add(refundJson);
|
||||
|
||||
JSONObject receiverJson = new JSONObject();
|
||||
receiverJson.put("acct_infos", refundArr);
|
||||
reqParams.put("acct_split_bunch", receiverJson.toJSONString());
|
||||
|
||||
log.info(logPrefix);
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/trade/payment/delaytrans/confirmrefund", payOrderDivisionRecord.getIfCode());
|
||||
JSONObject jsonData = response.getJSONObject("data");
|
||||
// 响应失败
|
||||
if (!DgPayKit.STATE_SUCCESS.equals(jsonData.getString("resp_code"))) {
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.confirmFail();
|
||||
// 状态失败
|
||||
DgPayKit.channelMsgError(jsonData, channelRetMsg);
|
||||
return channelRetMsg;
|
||||
}
|
||||
return ChannelRetMsg.confirmSuccess(jsonData.getString("hf_seq_id"));
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new BizException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long queryBalanceAmount(MchDivisionReceiver mchDivisionReceiver, MchAppConfigContext mchAppConfigContext) {
|
||||
String logPrefix = "【斗拱分账余额查询】";
|
||||
try {
|
||||
JSONObject paramsJson = JSONObject.parseObject(mchDivisionReceiver.getChannelAccNo());
|
||||
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis());
|
||||
// 商户号
|
||||
reqParams.put("huifu_id", paramsJson.getString("huifuId"));
|
||||
|
||||
log.info(logPrefix);
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/trade/acctpayment/balance/query", mchDivisionReceiver.getIfCode());
|
||||
JSONObject jsonData = response.getJSONObject("data");
|
||||
|
||||
Long balanceAmt = 0L;
|
||||
// 响应成功
|
||||
if (DgPayKit.STATE_SUCCESS.equals(jsonData.getString("resp_code"))) {
|
||||
// 账户信息列表
|
||||
JSONArray infoList = jsonData.getJSONArray("acctInfo_list");
|
||||
for (int i = 0; i < infoList.size(); i++) {
|
||||
JSONObject infoJson = JSONObject.parseObject(infoList.get(i).toString());
|
||||
// 查询基本账户类型
|
||||
if ("01".equals(infoJson.getString("acct_type"))) {
|
||||
balanceAmt = Long.parseLong(AmountUtil.convertDollar2Cent(infoJson.getString("balance_amt")));
|
||||
}
|
||||
}
|
||||
}
|
||||
return balanceAmt;
|
||||
} catch (Exception e) {
|
||||
throw new BizException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg cashout(MchDivisionReceiver mchDivisionReceiver, Long amount, MchAppConfigContext mchAppConfigContext) {
|
||||
String logPrefix = "斗拱分账账号提现";
|
||||
try {
|
||||
Long thisBalanceAmount = queryBalanceAmount(mchDivisionReceiver, mchAppConfigContext);
|
||||
if(thisBalanceAmount < amount){
|
||||
throw new BizException("商户可用余额不足");
|
||||
}
|
||||
JSONObject paramsJson = JSONObject.parseObject(mchDivisionReceiver.getChannelAccNo());
|
||||
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis());
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 商户号
|
||||
reqParams.put("huifu_id", paramsJson.getString("huifuId"));
|
||||
|
||||
// 取现卡序列号
|
||||
String tokenNo = paramsJson.getString("tokenNo");
|
||||
|
||||
if (StringUtils.isEmpty(tokenNo)) {
|
||||
throw new BizException("取现卡序列号不能为空");
|
||||
}
|
||||
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis() +"_"+ 1);
|
||||
// 到账类型
|
||||
reqParams.put("into_acct_date_type", "T0");
|
||||
// 取现卡序列号
|
||||
reqParams.put("token_no", tokenNo);
|
||||
// 取现金额
|
||||
reqParams.put("cash_amt", AmountUtil.convertCent2Dollar(amount));
|
||||
|
||||
log.info(logPrefix);
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/trade/settlement/enchashment", mchDivisionReceiver.getIfCode());
|
||||
JSONObject jsonData = response.getJSONObject("data");
|
||||
|
||||
// 响应成功
|
||||
if (DgPayKit.STATE_SUCCESS.equals(jsonData.getString("resp_code"))) {
|
||||
// 交易状态
|
||||
String transStat = jsonData.getString("trans_stat");
|
||||
if (DgPayKit.STATE_ING_P.equals(transStat)) {
|
||||
String channelNo = jsonData.getString("hf_seq_id");
|
||||
return ChannelRetMsg.confirmSuccess(channelNo);
|
||||
}else if (DgPayKit.STATE_FAIL_F.equals(transStat)) {
|
||||
return ChannelRetMsg.confirmFail(jsonData.getString("resp_code"), jsonData.getString("resp_desc"));
|
||||
}
|
||||
}
|
||||
return ChannelRetMsg.waiting();
|
||||
} catch (Exception e) {
|
||||
throw new BizException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
|
||||
import com.jeequan.jeepay.converter.MchInfoConverter;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.entity.MchInfo;
|
||||
import com.jeequan.jeepay.core.entity.MchSubInfo;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchAlipayConfigService;
|
||||
import com.jeequan.jeepay.core.model.applyment.ApplymentSignInfo;
|
||||
import com.jeequan.jeepay.core.model.applyment.DgpayApplymentInfo;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.core.utils.DateKit;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.db.entity.MchSubInfoEntity;
|
||||
import com.jeequan.jeepay.service.impl.MchApplymentService;
|
||||
import com.jeequan.jeepay.service.impl.MchSubInfoService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DgpayIsvmchAlipayConfigService implements IIsvmchAlipayConfigService {
|
||||
|
||||
@Autowired
|
||||
private MchSubInfoService mchSubInfoService;
|
||||
|
||||
@Autowired
|
||||
private MchApplymentService mchApplymentService;
|
||||
|
||||
@Autowired
|
||||
private MchInfoConverter mchInfoConverter;
|
||||
|
||||
private void realNameApply(MchApplyment mchApplyment, DgpayIsvParams isvParams) {
|
||||
DgpayApplymentInfo applymentInfo = JSON.parseObject(mchApplyment.getApplyDetailInfo(), DgpayApplymentInfo.class);
|
||||
|
||||
JSONObject suJson = JSON.parseObject(mchApplyment.getSuccResParameter());
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 汇付ID
|
||||
reqParams.put("huifu_id", suJson.getString("huifuId"));
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis() + "");
|
||||
|
||||
reqParams.put("pay_scene", "1");
|
||||
|
||||
// 主体信息
|
||||
JSONObject authIdentityInfo = new JSONObject();
|
||||
reqParams.put("auth_identity_info", authIdentityInfo);
|
||||
authIdentityInfo.put("business_type", getBusinessType(mchApplyment.getMerchantType()));
|
||||
authIdentityInfo.put("finance_institution_flag", "N");
|
||||
|
||||
if (mchApplyment.getMerchantType() == MchApplyment.MERCHANT_TYPE_PERSONAL) {
|
||||
JSONObject supportCredentials = new JSONObject();
|
||||
authIdentityInfo.put("support_credentials", supportCredentials);
|
||||
supportCredentials.put("micro_biz_type", applymentInfo.getMicroBizType());
|
||||
supportCredentials.put("store_name", applymentInfo.getMchShortName());
|
||||
supportCredentials.put("province_code", applymentInfo.getAreaCode().getString(0));
|
||||
if (applymentInfo.getAreaName() != null) {
|
||||
supportCredentials.put("province", applymentInfo.getAreaName().getString(0));
|
||||
}
|
||||
supportCredentials.put("city_code", applymentInfo.getAreaCode().getString(1));
|
||||
if (applymentInfo.getAreaName() != null) {
|
||||
supportCredentials.put("city", applymentInfo.getAreaName().getString(1));
|
||||
}
|
||||
supportCredentials.put("district_code", applymentInfo.getAreaCode().getString(2));
|
||||
if (applymentInfo.getAreaName() != null) {
|
||||
supportCredentials.put("district", applymentInfo.getAreaName().getString(2));
|
||||
}
|
||||
|
||||
if (applymentInfo.getMicroBizType().equals("MICRO_TYPE_MOBILE")) {
|
||||
supportCredentials.put("store_address", "无");
|
||||
} else {
|
||||
supportCredentials.put("store_address", applymentInfo.getAddress());
|
||||
}
|
||||
|
||||
String f49 = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F49", applymentInfo.getStoreOuterImg(), mchApplyment.getIfCode());
|
||||
supportCredentials.put("store_door_img", f49);
|
||||
|
||||
String f50 = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F50", applymentInfo.getStoreInnerImg(), mchApplyment.getIfCode());
|
||||
supportCredentials.put("store_inner_img", f50);
|
||||
} else {
|
||||
authIdentityInfo.put("certificate_type", "BUSINESS_CERT");
|
||||
|
||||
JSONObject certificateInfo = new JSONObject();
|
||||
authIdentityInfo.put("certificate_info", certificateInfo);
|
||||
certificateInfo.put("cert_number", applymentInfo.getLicenseNo());
|
||||
String f07 = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F07", applymentInfo.getLicenseImg(), mchApplyment.getIfCode());
|
||||
certificateInfo.put("cert_copy", f07);
|
||||
certificateInfo.put("cert_merchant_name", applymentInfo.getMchFullName());
|
||||
certificateInfo.put("cert_legal_person", applymentInfo.getIdcardName());
|
||||
certificateInfo.put("cert_company_address", applymentInfo.getLicenseAddress());
|
||||
certificateInfo.put("effect_time", applymentInfo.getLicenseEffectBegin().replace("-", ""));
|
||||
certificateInfo.put("expire_time", applymentInfo.getLicenseEffectEnd().replace("-", ""));
|
||||
}
|
||||
|
||||
JSONObject contactPersonInfo = new JSONObject();
|
||||
reqParams.put("contact_person_info", contactPersonInfo);
|
||||
contactPersonInfo.put("id_card_number", applymentInfo.getContactIdcardNo());
|
||||
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(mchApplyment);
|
||||
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/merchant/busi/ali/realname/apply", mchApplyment.getIfCode())
|
||||
.getJSONObject("data");
|
||||
|
||||
if (!DgPayKit.STATE_SUCCESS.equals(response.getString("resp_code"))) {
|
||||
throw new BizException(response.getString("resp_desc"));
|
||||
}
|
||||
|
||||
String applymentId = response.getString("applyment_id");
|
||||
String orderStatus = response.getString("order_status");
|
||||
|
||||
if (orderStatus.equals("AUDITING")) {
|
||||
suJson.put("zfb_applyment_id", applymentId);
|
||||
}
|
||||
mchApplyment.setSuccResParameter(suJson.toJSONString());
|
||||
mchApplymentService.updateById(mchInfoConverter.toDbEntity(mchApplyment));
|
||||
}
|
||||
|
||||
private String getBusinessType(Byte merchantType) {
|
||||
if (merchantType == MchApplyment.MERCHANT_TYPE_PERSONAL) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
if (merchantType == MchApplyment.MERCHANT_TYPE_INDIVIDUAL) {
|
||||
return "5";
|
||||
}
|
||||
|
||||
if (merchantType == MchApplyment.MERCHANT_TYPE_ENTERPRISE) {
|
||||
return "3";
|
||||
}
|
||||
|
||||
throw new BizException("无法判定的其他主体类型");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplymentSignInfo alipayOpenSignInfo(MchApplyment mchApplyment) {
|
||||
|
||||
// 服务商配置参数
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
DgpayIsvParams isvParams = (DgpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment.getIsvNo(), mchApplyment.getIfCode());
|
||||
|
||||
ApplymentSignInfo result = new ApplymentSignInfo();
|
||||
|
||||
// 进件商户信息
|
||||
JSONObject suJson = JSON.parseObject(mchApplyment.getSuccResParameter());
|
||||
if (suJson == null || StringUtils.isEmpty(suJson.getString("huifuId"))) {
|
||||
result.setState("查询失败");
|
||||
result.setErrInfo("商户参数为空,该商户还未进件成功");
|
||||
return result;
|
||||
}
|
||||
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(mchApplyment);
|
||||
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 汇付ID
|
||||
reqParams.put("huifu_id", suJson.getString("huifuId"));
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis() + "");
|
||||
|
||||
// 发送请求
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/merchant/busi/realname/query", mchApplyment.getIfCode())
|
||||
.getJSONObject("data");
|
||||
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis() + "_info");
|
||||
// 商户详情is_open_small_flag -> 0
|
||||
JSONObject mchInfo = DgPayKit.request(mchAppConfigContext, reqParams, "/merchant/basicdata/query", mchApplyment.getIfCode());
|
||||
JSONObject mchInfoData = mchInfo.getJSONObject("data");
|
||||
String feeConfig = "";
|
||||
JSONArray wxConfList = mchInfoData.getJSONArray("qry_wx_conf_list");
|
||||
JSONArray aliConfList = mchInfoData.getJSONArray("qry_ali_conf_list");
|
||||
JSONObject unionConf = mchInfoData.getJSONObject("qry_union_conf");
|
||||
JSONObject bankCardConf = mchInfoData.getJSONObject("qry_bank_card_conf");
|
||||
|
||||
for (int aliIndex = 0; aliIndex < aliConfList.size(); aliIndex++) {
|
||||
JSONArray aliMerInfos = aliConfList.getJSONObject(aliIndex).getJSONArray("ali_mer_infos");
|
||||
|
||||
if (!CollUtil.isEmpty(aliMerInfos)) {
|
||||
|
||||
for (int i = 0; i < aliMerInfos.size(); i++) {
|
||||
JSONObject item = aliMerInfos.getJSONObject(i);
|
||||
// 支付宝子商户号存在时
|
||||
MchSubInfoEntity zfbSubInfo = new MchSubInfoEntity();
|
||||
zfbSubInfo.setMchApplyId(mchApplyment.getApplyId());
|
||||
|
||||
String payChannelId = item.getString("pay_channel_id");
|
||||
String bankMerCode = item.getString("bank_mer_code");
|
||||
if (Objects.equals(isvParams.getChannelNo(), payChannelId)) {
|
||||
zfbSubInfo.setMainUse(1);
|
||||
result.setChannelSubMchId(bankMerCode);
|
||||
} else {
|
||||
zfbSubInfo.setMainUse(0);
|
||||
}
|
||||
zfbSubInfo.setSubMchWay("DG");
|
||||
zfbSubInfo.setChannelMchNo(mchApplyment.getChannelMchNo());
|
||||
zfbSubInfo.setChannelId(payChannelId);
|
||||
zfbSubInfo.setAuthStatus(MchSubInfo.AUTH_STATUS_UNAUTHORIZED);
|
||||
zfbSubInfo.setSubMchId(bankMerCode);
|
||||
zfbSubInfo.setSubMchType("ZFB");
|
||||
// 此处取1为正常
|
||||
zfbSubInfo.setStatus("1");
|
||||
zfbSubInfo.setExt(item);
|
||||
|
||||
try {
|
||||
mchSubInfoService.save(zfbSubInfo);
|
||||
} catch (DuplicateKeyException e) {
|
||||
log.info("子商户信息已存储过");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 支付宝申请单编号
|
||||
// String applymentId = suJson.getString("zfb_applyment_id");
|
||||
// if (applymentId == null) {
|
||||
// realNameApply(mchApplyment, isvParams);
|
||||
// }
|
||||
|
||||
reqParams = new JSONObject();
|
||||
// 汇付ID
|
||||
reqParams.put("huifu_id", suJson.getString("huifuId"));
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis() + "");
|
||||
// reqParams.put("pay_channel_id", DateKit.currentTimeMillis()+"");
|
||||
// reqParams.put("pay_scene", "1");
|
||||
|
||||
// 发送请求
|
||||
JSONObject response2 = DgPayKit.request(mchAppConfigContext, reqParams, "/merchant/busi/ali/realname/query", mchApplyment.getIfCode())
|
||||
.getJSONObject("data");
|
||||
|
||||
String respCode = response2.getString("resp_code");
|
||||
String respDesc = response2.getString("resp_desc");
|
||||
|
||||
if (!respCode.equals("00000000")) {
|
||||
result.setState("获取子商户状态异常");
|
||||
result.setErrInfo("【" + respDesc + "】");
|
||||
result.setImgType("qrContent");
|
||||
result.setSignUrl(isvParams.getAliChannelExtUrl());
|
||||
return result;
|
||||
}
|
||||
|
||||
String orderStatus = response2.getString("order_status");
|
||||
if ("AUDITING".equals(orderStatus)) {
|
||||
result.setState("审核中");
|
||||
} else if ("CONTACT_CONFIRM".equals(orderStatus)) {
|
||||
result.setState("待联系人确认(扫码确认授权)");
|
||||
result.setImgType("imgUrl");
|
||||
result.setSignUrl(response2.getString("qrcode"));
|
||||
} else if ("LEGAL_CONFIRM".equals(orderStatus)) {
|
||||
result.setState("待法人确认(扫码确认授权)");
|
||||
result.setImgType("imgUrl");
|
||||
result.setSignUrl(response2.getString("qrcode"));
|
||||
} else if ("AUDIT_PASS".equals(orderStatus)) {
|
||||
result.setState("审核通过");
|
||||
} else if ("AUDIT_REJECT".equals(orderStatus)) {
|
||||
result.setState("审核失败");
|
||||
} else if ("AUDIT_FREEZE".equals(orderStatus)) {
|
||||
result.setState("已冻结(扫码确认授权)");
|
||||
result.setImgType("imgUrl");
|
||||
result.setSignUrl(response2.getString("qrcode"));
|
||||
} else if ("CANCELED".equals(orderStatus)) {
|
||||
result.setState("已撤回");
|
||||
} else if ("NOT_APPLY".equals(orderStatus)) {
|
||||
result.setState("未申请");
|
||||
}
|
||||
|
||||
String authorizeStat = response2.getString("authorize_stat");
|
||||
|
||||
LambdaUpdateChainWrapper<MchSubInfoEntity> stateUpdate = mchSubInfoService.lambdaUpdate()
|
||||
.eq(MchSubInfoEntity::getMchApplyId, mchApplyment.getApplyId())
|
||||
.eq(MchSubInfoEntity::getMainUse, 1)
|
||||
.eq(MchSubInfoEntity::getSubMchType, "ZFB");
|
||||
|
||||
if ("AUTHORIZED".equals(authorizeStat)) {
|
||||
stateUpdate.set(MchSubInfoEntity::getAuthStatus, MchSubInfo.AUTH_STATUS_AUTHORIZED).update();
|
||||
result.setState("已授权");
|
||||
} else if ("UNAUTHORIZED".equals(authorizeStat)) {
|
||||
stateUpdate.set(MchSubInfoEntity::getAuthStatus, MchSubInfo.AUTH_STATUS_UNAUTHORIZED).update();
|
||||
result.setState("未授权");
|
||||
} else if ("CLOSED".equals(authorizeStat)) {
|
||||
result.setState("已销户");
|
||||
} else {
|
||||
result.setState("未报备");
|
||||
}
|
||||
|
||||
|
||||
if (ObjUtil.isEmpty(result.getSignUrl())) {
|
||||
// 渠道拓展地址
|
||||
result.setImgType("qrContent");
|
||||
result.setSignUrl(isvParams.getAliChannelExtUrl());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.converter.MchInfoConverter;
|
||||
import com.jeequan.jeepay.core.beans.RequestKitBean;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.entity.MchModifyApplyment;
|
||||
import com.jeequan.jeepay.core.entity.MchSubInfo;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchApplymentNotifyService;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.db.entity.MchModifyApplymentEntity;
|
||||
import com.jeequan.jeepay.service.impl.MchApplymentService;
|
||||
import com.jeequan.jeepay.service.impl.MchModifyApplymentService;
|
||||
import com.jeequan.jeepay.service.impl.MchSubInfoService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DgpayIsvmchApplymentNotifyService implements IIsvmchApplymentNotifyService {
|
||||
|
||||
@Autowired
|
||||
private RequestKitBean requestKitBean;
|
||||
|
||||
@Autowired
|
||||
private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Autowired
|
||||
private MchApplymentService mchApplymentService;
|
||||
|
||||
@Autowired
|
||||
private MchInfoConverter mchInfoConverter;
|
||||
|
||||
@Autowired
|
||||
private MchSubInfoService mchSubInfoService;
|
||||
|
||||
@Autowired
|
||||
private MchModifyApplymentService modifyApplymentService;
|
||||
|
||||
@Override
|
||||
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlApplyId) {
|
||||
JSONObject reqParamJSON = requestKitBean.getReqParamJSON();
|
||||
|
||||
JSONObject data = reqParamJSON.getJSONObject("data");
|
||||
|
||||
String applyNo = data.getString("apply_no");
|
||||
|
||||
com.jeequan.jeepay.db.entity.MchApplyment mchApplyment = mchApplymentService.getByOrderId(applyNo);
|
||||
if (mchApplyment == null) {
|
||||
// 此时查询变更的申请单
|
||||
MchModifyApplymentEntity mchModifyApplyment = modifyApplymentService.getByOrderId(applyNo, CS.IF_CODE.DGPAY);
|
||||
if (mchModifyApplyment == null) {
|
||||
return MutablePair.of(null, data);
|
||||
}
|
||||
mchApplyment = mchApplymentService.getByChannelMchNo(mchModifyApplyment.getChannelMchNo());
|
||||
}
|
||||
|
||||
if (mchApplyment == null) {
|
||||
return MutablePair.of(null, data);
|
||||
}
|
||||
|
||||
DgpayIsvParams isvParams = (DgpayIsvParams) configContextQueryService.queryIsvParams(mchInfoConverter.toModel(mchApplyment));
|
||||
|
||||
|
||||
boolean verify = DgPayKit.verify(data.toJSONString(), isvParams.getRsaPublicKey(), reqParamJSON.getString("sign"));
|
||||
if (!verify) {
|
||||
log.info("斗拱支付回调参数验签不通过");
|
||||
}
|
||||
|
||||
return MutablePair.of(mchApplyment.getApplyId(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchApplyment, ResponseEntity> doNotify(HttpServletRequest request, Object params, MchApplyment mchApplyment) {
|
||||
|
||||
JSONObject response = ((JSONObject) params);
|
||||
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String notifyType = resData.getString("notify_type");
|
||||
|
||||
if (response.getString("apply_no").equals(mchApplyment.getChannelApplyNo())) {
|
||||
// 入网回调
|
||||
if (CharSequenceUtil.isEmpty(notifyType)) {
|
||||
applyResult(resData, mchApplyment);
|
||||
} else {
|
||||
// 报备回调
|
||||
reportResult(resData, mchApplyment);
|
||||
|
||||
return MutablePair.of(mchApplyment, retOk("RECV_ORD_ID_" + resData.getString("ord_id")));
|
||||
}
|
||||
} else {
|
||||
MchModifyApplymentEntity mchModifyApplyment = modifyApplymentService.getByOrderId(response.getString("apply_no"), CS.IF_CODE.DGPAY);
|
||||
// 变更回调
|
||||
changeResult(resData, mchInfoConverter.toModel(mchModifyApplyment));
|
||||
}
|
||||
|
||||
return MutablePair.of(mchApplyment, retOk(null));
|
||||
}
|
||||
|
||||
private void changeResult(JSONObject resData, MchModifyApplyment modifyApplyment) {
|
||||
String auditStatus = resData.getString("audit_status");
|
||||
String auditDesc = resData.getString("audit_desc");
|
||||
|
||||
MchModifyApplymentEntity result = new MchModifyApplymentEntity();
|
||||
result.setModifyApplyId(modifyApplyment.getModifyApplyId());
|
||||
if ("Y".equals(auditStatus)) {
|
||||
// 变更成功
|
||||
modifyApplymentService.localModify(modifyApplyment);
|
||||
} else if ("N".equals(auditStatus) || "F".equals(auditStatus)) {
|
||||
// 变更失败
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo("[" + auditDesc + "]");
|
||||
|
||||
modifyApplymentService.updateById(result);
|
||||
}
|
||||
}
|
||||
|
||||
private void reportResult(JSONObject resData, MchApplyment mchApplyment) {
|
||||
MchApplyment result = new MchApplyment();
|
||||
result.setApplyId(mchApplyment.getApplyId());
|
||||
String code = resData.getString("sub_resp_code");
|
||||
String notifyType = resData.getString("notify_type");
|
||||
String huifuId = resData.getString("huifu_id");
|
||||
|
||||
if (!"00000000".equals(code)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MchSubInfo mchSubInfo = new MchSubInfo();
|
||||
mchSubInfo.setChannelMchNo(huifuId);
|
||||
mchSubInfo.setAuthStatus(MchSubInfo.AUTH_STATUS_UNAUTHORIZED);
|
||||
switch (notifyType) {
|
||||
case "W":
|
||||
mchSubInfo.setSubMchType("WX");
|
||||
break;
|
||||
case "A":
|
||||
mchSubInfo.setSubMchType("ZFB");
|
||||
break;
|
||||
case "U":
|
||||
mchSubInfo.setSubMchType("BANK");
|
||||
break;
|
||||
default:
|
||||
}
|
||||
// 通知类型,没有则是申请单审核异步回调
|
||||
|
||||
JSONArray regResultList = resData.getJSONArray("reg_result_list");
|
||||
|
||||
if (regResultList == null || regResultList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < regResultList.size(); i++) {
|
||||
JSONObject item = regResultList.getJSONObject(i);
|
||||
|
||||
MchSubInfo newEntity = mchInfoConverter.clone(mchSubInfo);
|
||||
newEntity.setExt(item);
|
||||
newEntity.setStatus(item.getString("business_stat"));
|
||||
newEntity.setSubMchId(item.getString("sub_mer_id"));
|
||||
newEntity.setChannelId(item.getString("pay_channel_id"));
|
||||
mchSubInfoService.save(mchInfoConverter.toDbEntity(newEntity));
|
||||
}
|
||||
}
|
||||
|
||||
private void applyResult(JSONObject resData, MchApplyment mchApplyment) {
|
||||
MchApplyment result = new MchApplyment();
|
||||
result.setApplyId(mchApplyment.getApplyId());
|
||||
String code = resData.getString("sub_resp_code");
|
||||
|
||||
if ("00000000".equals(code)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String auditStatus = resData.getString("audit_status");
|
||||
String auditDesc = resData.getString("audit_desc");
|
||||
// 通知类型,没有则是申请单审核异步回调
|
||||
|
||||
if ("Y".equals(auditStatus)) {
|
||||
String huifuId = resData.getString("huifu_id");
|
||||
// 进件查询响应参数
|
||||
result.setApplyErrorInfo("[" + auditDesc + "]");
|
||||
result.setState(MchApplyment.STATE_SUCCESS);
|
||||
result.setChannelMchNo(huifuId);
|
||||
result.setSuccResParameter(resData.toString());
|
||||
mchApplymentService.updateById(mchInfoConverter.toDbEntity(result));
|
||||
} else if ("N".equals(auditStatus) || "F".equals(auditStatus)) {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo("[" + auditDesc + "]");
|
||||
mchApplymentService.updateById(mchInfoConverter.toDbEntity(result));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<?> retOk(Object params) {
|
||||
return ResponseEntity.ok("SUCCESS");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,634 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.entity.MchInfo;
|
||||
import com.jeequan.jeepay.core.entity.MchModifyApplyment;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchModifyApplymentService;
|
||||
import com.jeequan.jeepay.core.model.applyment.DgpayApplymentInfo;
|
||||
import com.jeequan.jeepay.core.model.applyment.MchModifyApplymentModel;
|
||||
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DgpayIsvmchModifyApplymentService implements IIsvmchModifyApplymentService {
|
||||
|
||||
@Autowired
|
||||
protected SysConfigService sysConfigService;
|
||||
|
||||
@Autowired
|
||||
private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> localModifyBase(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();
|
||||
MchApplyment resultMchApplyment = new MchApplyment();
|
||||
|
||||
MchModifyApplyment mchModifyApplyment = mchDataPair.getKey();
|
||||
resultModifyApplyment.setModifyApplyId(mchModifyApplyment.getModifyApplyId());
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_SUCCESS);
|
||||
MchApplyment mchApplyment = mchDataPair.getValue();
|
||||
resultMchApplyment.setApplyId(mchApplyment.getApplyId());
|
||||
|
||||
String applyDetailInfo = mchModifyApplyment.getApplyDetailInfo();
|
||||
MchModifyApplymentModel mchModifyData = JSON.parseObject(applyDetailInfo, MchModifyApplymentModel.class);
|
||||
|
||||
String originApplyDetailInfo = mchApplyment.getApplyDetailInfo();
|
||||
DgpayApplymentInfo originMchModifyData = JSON.parseObject(originApplyDetailInfo, DgpayApplymentInfo.class);
|
||||
resultMchApplyment.setApplyDetailInfo(JSON.toJSONString(originMchModifyData));
|
||||
|
||||
originMchModifyData.setMchShortName(mchModifyData.getMchShortName());
|
||||
resultMchApplyment.setMchShortName(mchModifyData.getMchShortName());
|
||||
|
||||
return new MutablePair<>(resultModifyApplyment, resultMchApplyment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> localModifySettlement(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();
|
||||
MchApplyment resultMchApplyment = new MchApplyment();
|
||||
|
||||
MchModifyApplyment mchModifyApplyment = mchDataPair.getKey();
|
||||
resultModifyApplyment.setModifyApplyId(mchModifyApplyment.getModifyApplyId());
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_SUCCESS);
|
||||
MchApplyment mchApplyment = mchDataPair.getValue();
|
||||
resultMchApplyment.setApplyId(mchApplyment.getApplyId());
|
||||
|
||||
String applyDetailInfo = mchModifyApplyment.getApplyDetailInfo();
|
||||
MchModifyApplymentModel mchModifyData = JSON.parseObject(applyDetailInfo, MchModifyApplymentModel.class);
|
||||
|
||||
String originApplyDetailInfo = mchApplyment.getApplyDetailInfo();
|
||||
DgpayApplymentInfo originMchModifyData = JSON.parseObject(originApplyDetailInfo, DgpayApplymentInfo.class);
|
||||
resultMchApplyment.setApplyDetailInfo(JSON.toJSONString(originMchModifyData));
|
||||
|
||||
originMchModifyData.setSettAccountType(mchModifyData.getSettAccountType());
|
||||
if ("Y".equals(mchModifyData.getIllegal())) {
|
||||
originMchModifyData.setSettAccountIdcardNo(mchModifyData.getSettAccountIdcardNo());
|
||||
originMchModifyData.setSettAccountIdcard1Img(mchModifyData.getSettAccountIdcard1Img());
|
||||
originMchModifyData.setSettAccountIdcard2Img(mchModifyData.getSettAccountIdcard2Img());
|
||||
originMchModifyData.setSettAccountIdcardEffectBegin(mchModifyData.getSettAccountIdcardEffectBegin());
|
||||
originMchModifyData.setSettAccountIdcardEffectEnd(mchModifyData.getSettAccountIdcardEffectEnd());
|
||||
}
|
||||
|
||||
originMchModifyData.setSettAccountLicenseImg(mchModifyData.getSettAccountLicenseImg());
|
||||
originMchModifyData.setSettAccountName(mchModifyData.getSettAccountName());
|
||||
originMchModifyData.setSettAccountNo(mchModifyData.getSettAccountNo());
|
||||
originMchModifyData.setSettAccountBankName(mchModifyData.getSettAccountBankName());
|
||||
originMchModifyData.setAuthEnturstPic(mchModifyData.getNonLegSettleAuthPic());
|
||||
|
||||
return new MutablePair<>(resultModifyApplyment, resultMchApplyment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> localModifyRate(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> syncChannelModifyBase(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();
|
||||
|
||||
MchModifyApplyment mchModifyApplyment = mchDataPair.getKey();
|
||||
resultModifyApplyment.setModifyApplyId(mchModifyApplyment.getModifyApplyId());
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
|
||||
MchApplyment mchApplyment = mchDataPair.getValue();
|
||||
|
||||
String applyDetailInfo = mchModifyApplyment.getApplyDetailInfo();
|
||||
MchModifyApplymentModel mchModifyData = JSON.parseObject(applyDetailInfo, MchModifyApplymentModel.class);
|
||||
|
||||
DgpayIsvParams isvParams = ((DgpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment));
|
||||
|
||||
JSONObject param = new JSONObject();
|
||||
Date today = new Date();
|
||||
String formatDate = DateUtil.format(today, DatePattern.PURE_DATE_PATTERN);
|
||||
param.put("req_seq_id", formatDate + mchModifyApplyment.getApplyId());
|
||||
param.put("req_date", formatDate);
|
||||
param.put("upper_huifu_id", isvParams.getSysId());
|
||||
param.put("huifu_id", mchApplyment.getChannelMchNo());
|
||||
param.put("short_name", mchModifyData.getMchShortName());
|
||||
param.put("async_return_url", getCallbackUrl(mchApplyment.getIfCode()));
|
||||
|
||||
JSONObject agreementInfo = new JSONObject();
|
||||
agreementInfo.put("agreement_type", "0");
|
||||
param.put("agreement_info", agreementInfo.toJSONString());
|
||||
|
||||
JSONObject signUserInfo = new JSONObject();
|
||||
param.put("sign_user_info", signUserInfo);
|
||||
|
||||
DgpayApplymentInfo applymentInfo = JSON.parseObject(mchApplyment.getApplyDetailInfo(), DgpayApplymentInfo.class);
|
||||
switch (applymentInfo.getSettAccountType()) {
|
||||
case "B":
|
||||
case "C":
|
||||
// 对公
|
||||
signUserInfo.put("type", "LEGAL");
|
||||
signUserInfo.put("mobile_no", applymentInfo.getIdCardPhone());
|
||||
break;
|
||||
case "D":
|
||||
signUserInfo.put("type", "OTHER");
|
||||
signUserInfo.put("name", applymentInfo.getSettAccountName());
|
||||
signUserInfo.put("mobile_no", applymentInfo.getSettAccountBindPhone());
|
||||
signUserInfo.put("cert_no", applymentInfo.getSettAccountIdcardNo());
|
||||
break;
|
||||
}
|
||||
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(mchApplyment);
|
||||
|
||||
try {
|
||||
JSONObject applyResp = DgPayKit.request(mchAppConfigContext, param, DgPayKit.MCH_APPLY_MODIFY_URL, mchApplyment.getIfCode());
|
||||
JSONObject applyRespData = applyResp.getJSONObject("data");
|
||||
String code = applyRespData.getString("sub_resp_code");
|
||||
String msg = applyRespData.getString("sub_resp_desc");
|
||||
|
||||
if ("00000000".equals(code)) {
|
||||
// 请求成功
|
||||
String applyNo = applyRespData.getString("apply_no");
|
||||
resultModifyApplyment.setChannelApplyNo(applyNo);
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_SUCCESS);
|
||||
return localModifyBase(new MutablePair<>(resultModifyApplyment, mchDataPair.right));
|
||||
} else if ("90000000".equals(code)) {
|
||||
// 审核中
|
||||
String applyNo = applyRespData.getString("apply_no");
|
||||
resultModifyApplyment.setChannelApplyNo(applyNo);
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
|
||||
} else {
|
||||
// 其他暂定为失败
|
||||
resultModifyApplyment.setApplyErrorInfo("[" + msg + "]");
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
}
|
||||
|
||||
resultModifyApplyment.setChannelVar1(applyRespData.toJSONString());
|
||||
|
||||
String remark = "斗拱支付基本信息变更已发起";
|
||||
resultModifyApplyment.setRemark(remark);
|
||||
log.debug("斗拱支付基本信息变更发起成功");
|
||||
} catch (Exception e) {
|
||||
resultModifyApplyment.setApplyErrorInfo("[" + e.getMessage() + "]");
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
}
|
||||
|
||||
return new MutablePair<>(resultModifyApplyment, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> syncChannelModifySettlement(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();
|
||||
|
||||
MchModifyApplyment mchModifyApplyment = mchDataPair.getKey();
|
||||
resultModifyApplyment.setModifyApplyId(mchModifyApplyment.getModifyApplyId());
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
|
||||
MchApplyment mchApplyment = mchDataPair.getValue();
|
||||
|
||||
String applyDetailInfo = mchModifyApplyment.getApplyDetailInfo();
|
||||
MchModifyApplymentModel mchModifyData = JSON.parseObject(applyDetailInfo, MchModifyApplymentModel.class);
|
||||
|
||||
DgpayIsvParams isvParams = ((DgpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment));
|
||||
|
||||
JSONObject param = new JSONObject();
|
||||
Date today = new Date();
|
||||
String formatDate = DateUtil.format(today, DatePattern.PURE_DATE_PATTERN);
|
||||
param.put("req_seq_id", formatDate + mchModifyApplyment.getApplyId());
|
||||
param.put("req_date", formatDate);
|
||||
param.put("upper_huifu_id", isvParams.getSysId());
|
||||
param.put("huifu_id", mchApplyment.getChannelMchNo());
|
||||
|
||||
param.put("async_return_url", getCallbackUrl(mchApplyment.getIfCode()));
|
||||
|
||||
JSONObject cardInfo = new JSONObject();
|
||||
|
||||
if ("B".equals(mchModifyData.getSettAccountType())) {
|
||||
String f13 = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F13", mchModifyData.getSettAccountLicenseImg(), mchApplyment.getIfCode());
|
||||
cardInfo.put("settle_card_front_pic", f13);
|
||||
} else {
|
||||
String f08 = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F08", mchModifyData.getChangeFormPic(), mchApplyment.getIfCode());
|
||||
cardInfo.put("reg_acct_pic", f08);
|
||||
}
|
||||
String f55 = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F55", mchModifyData.getSettAccountIdcard1Img(), mchApplyment.getIfCode());
|
||||
cardInfo.put("settle_cert_front_pic", f55);
|
||||
String f56 = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F56", mchModifyData.getSettAccountIdcard2Img(), mchApplyment.getIfCode());
|
||||
cardInfo.put("settle_cert_back_pic", f56);
|
||||
String f15 = DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F15", mchModifyData.getNonLegSettleAuthPic(), mchApplyment.getIfCode());
|
||||
cardInfo.put("auth_enturst_pic", f15);
|
||||
|
||||
param.put("card_info", cardInfo);
|
||||
if ("Y".equals(mchModifyData.getIllegal())) {
|
||||
cardInfo.put("card_type", "2");
|
||||
} else {
|
||||
if ("B".equals(mchModifyData.getSettAccountType())) {
|
||||
cardInfo.put("card_type", "0");
|
||||
} else {
|
||||
cardInfo.put("card_type", "1");
|
||||
}
|
||||
}
|
||||
|
||||
if (!"B".equals(mchModifyData.getSettAccountType())) {
|
||||
cardInfo.put("prov_id", mchModifyData.getSettAccountBankBranchAreaCode().getString(0));
|
||||
cardInfo.put("area_id", mchModifyData.getSettAccountBankBranchAreaCode().getString(1));
|
||||
} else {
|
||||
cardInfo.put("branch_code", mchModifyData.getBankSubCode());
|
||||
cardInfo.put("branch_name", mchModifyData.getSettAccountBankBranchName());
|
||||
}
|
||||
|
||||
cardInfo.put("card_name", mchModifyData.getSettAccountName());
|
||||
cardInfo.put("card_no", mchModifyData.getSettAccountNo());
|
||||
cardInfo.put("bank_code", mchModifyData.getBankCode());
|
||||
|
||||
if ("Y".equals(mchModifyData.getIllegal())) {
|
||||
cardInfo.put("cert_validity_type", mchModifyData.getSettAccountIdcardEffectEnd().equals("长期")? "1": "0");
|
||||
cardInfo.put("cert_begin_date", mchModifyData.getSettAccountIdcardEffectBegin().replace("-", ""));
|
||||
if (!mchModifyData.getSettAccountIdcardEffectEnd().equals("长期")) {
|
||||
cardInfo.put("cert_end_date", mchModifyData.getSettAccountIdcardEffectEnd().replace("-", ""));
|
||||
}
|
||||
cardInfo.put("cert_no", mchModifyData.getSettAccountIdcardNo());
|
||||
cardInfo.put("cert_type", "00");
|
||||
cardInfo.put("mp", mchModifyData.getPhone());
|
||||
}
|
||||
|
||||
|
||||
if ("Y".equals(mchModifyData.getIllegal())) {
|
||||
cardInfo.put("card_type", "2");
|
||||
}
|
||||
|
||||
cardInfo.put("card_type", mchModifyData.getMchShortName());
|
||||
cardInfo.put("receipt_name", mchModifyData.getMchShortName());
|
||||
param.put("deal_type", "1");
|
||||
|
||||
JSONObject agreementInfo = new JSONObject();
|
||||
agreementInfo.put("agreement_type", "0");
|
||||
param.put("agreement_info", agreementInfo.toJSONString());
|
||||
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(mchApplyment);
|
||||
|
||||
try {
|
||||
JSONObject applyResp = DgPayKit.request(mchAppConfigContext, param, DgPayKit.MCH_APPLY_MODIFY_URL, mchApplyment.getIfCode());
|
||||
JSONObject applyRespData = applyResp.getJSONObject("data");
|
||||
String code = applyRespData.getString("sub_resp_code");
|
||||
String msg = applyRespData.getString("sub_resp_desc");
|
||||
|
||||
if ("00000000".equals(code)) {
|
||||
// 请求成功
|
||||
String applyNo = applyRespData.getString("apply_no");
|
||||
resultModifyApplyment.setChannelApplyNo(applyNo);
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
|
||||
} else if ("90000000".equals(code)) {
|
||||
// 审核中
|
||||
String applyNo = applyRespData.getString("apply_no");
|
||||
resultModifyApplyment.setChannelApplyNo(applyNo);
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
|
||||
} else {
|
||||
// 其他暂定为失败
|
||||
resultModifyApplyment.setApplyErrorInfo("[" + msg + "]");
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
}
|
||||
|
||||
String changeSysFlowId = applyRespData.getString("changeSysFlowId");
|
||||
|
||||
resultModifyApplyment.setChannelApplyNo(changeSysFlowId);
|
||||
resultModifyApplyment.setChannelVar1(applyRespData.toJSONString());
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
|
||||
|
||||
String remark = "斗拱支付结算信息变更已发起";
|
||||
resultModifyApplyment.setRemark(remark);
|
||||
log.debug("斗拱支付结算信息变更发起成功");
|
||||
} catch (Exception e) {
|
||||
resultModifyApplyment.setApplyErrorInfo("[" + e.getMessage() + "]");
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
}
|
||||
|
||||
return new MutablePair<>(resultModifyApplyment, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> syncChannelModifyRate(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> syncChannelModifySettlementType(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();
|
||||
|
||||
MchModifyApplyment mchModifyApplyment = mchDataPair.getKey();
|
||||
resultModifyApplyment.setModifyApplyId(mchModifyApplyment.getModifyApplyId());
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
|
||||
MchApplyment mchApplyment = mchDataPair.getValue();
|
||||
|
||||
String applyDetailInfo = mchModifyApplyment.getApplyDetailInfo();
|
||||
MchModifyApplymentModel mchModifyData = JSON.parseObject(applyDetailInfo, MchModifyApplymentModel.class);
|
||||
|
||||
DgpayApplymentInfo applymentInfo = JSON.parseObject(mchDataPair.right.getApplyDetailInfo(), DgpayApplymentInfo.class);
|
||||
|
||||
DgpayIsvParams isvParams = ((DgpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment));
|
||||
|
||||
JSONObject param = new JSONObject();
|
||||
Date today = new Date();
|
||||
String formatDate = DateUtil.format(today, DatePattern.PURE_DATE_PATTERN);
|
||||
param.put("req_seq_id", formatDate + mchModifyApplyment.getApplyId());
|
||||
param.put("req_date", formatDate);
|
||||
param.put("upper_huifu_id", isvParams.getSysId());
|
||||
param.put("huifu_id", mchApplyment.getChannelMchNo());
|
||||
|
||||
JSONObject settleConfig = new JSONObject();
|
||||
settleConfig.put("settle_status", "1");
|
||||
settleConfig.put("settle_cycle", mchModifyData.getSettlementType());
|
||||
|
||||
PaywayFee d0 = null;
|
||||
PaywayFee d1 = null;
|
||||
for (PaywayFee paywayFee : applymentInfo.getPaywayFeeList()) {
|
||||
if (CS.PAY_WAY_CODE.D0.equals(paywayFee.getFeeType())) {
|
||||
d0 = paywayFee;
|
||||
}
|
||||
if (CS.PAY_WAY_CODE.D1.equals(paywayFee.getFeeType())) {
|
||||
d1 = paywayFee;
|
||||
}
|
||||
}
|
||||
|
||||
if (d1 != null) {
|
||||
settleConfig.put("fixed_ratio", DgpayApplymentInfo.convertRate(d1.getFeeRate()));
|
||||
} else {
|
||||
// 默认D1提现费率为0.01%
|
||||
settleConfig.put("fixed_ratio", "0.01");
|
||||
}
|
||||
|
||||
param.put("settle_config", settleConfig.toJSONString());
|
||||
|
||||
JSONObject signUserInfo = new JSONObject();
|
||||
signUserInfo.put("type", "LEGAL");
|
||||
signUserInfo.put("mobile_no", mchApplyment.getContactPhone());
|
||||
|
||||
param.put("sign_user_info", signUserInfo);
|
||||
|
||||
param.put("async_return_url", getCallbackUrl(mchApplyment.getIfCode()));
|
||||
|
||||
JSONObject cashConfig = new JSONObject();
|
||||
param.put("deal_type", "2");
|
||||
|
||||
cashConfig.put("switch_state", "0");
|
||||
cashConfig.put("cash_type", mchModifyData.getSettlementType());
|
||||
|
||||
|
||||
|
||||
if (d0 != null) {
|
||||
cashConfig.put("fee_rate", DgpayApplymentInfo.convertRate(d0.getFeeRate()));
|
||||
} else {
|
||||
// 默认D0提现费率设置为 0.1%
|
||||
cashConfig.put("fee_rate", "0.10");
|
||||
}
|
||||
|
||||
// 电子协议
|
||||
JSONObject agreementInfo = new JSONObject();
|
||||
agreementInfo.put("agreement_type", "0");
|
||||
param.put("agreement_info", agreementInfo.toJSONString());
|
||||
|
||||
// 结算卡信息
|
||||
JSONObject cardInfoJson = new JSONObject();
|
||||
|
||||
DgpayApplymentInfo info = JSON.parseObject(mchApplyment.getApplyDetailInfo(), DgpayApplymentInfo.class);
|
||||
String settAccountType = info.getSettAccountType();
|
||||
if ("B".equals(settAccountType)) {
|
||||
// 对公
|
||||
cardInfoJson.put("card_type", "0");
|
||||
// 持卡人证件类型 默认为身份证
|
||||
cardInfoJson.put("cert_type", "");
|
||||
// 银行编码
|
||||
cardInfoJson.put("bank_code", info.getBankCode());
|
||||
// 联行号
|
||||
cardInfoJson.put("branch_code", info.getBranchCode());
|
||||
// 支行名称
|
||||
cardInfoJson.put("branch_name", info.getBranchName());
|
||||
|
||||
cardInfoJson.put("mp", "");
|
||||
|
||||
// 签约人类型
|
||||
// signUserInfoJson.put("type", "LEGAL");
|
||||
|
||||
} else if ("C".equals(settAccountType)) {
|
||||
cardInfoJson.put("mp", info.getSettAccountBindPhone());
|
||||
|
||||
// 对私
|
||||
cardInfoJson.put("card_type", "1");
|
||||
// 持卡人证件类型 默认为身份证
|
||||
cardInfoJson.put("cert_type", "00");
|
||||
// 持卡人证件号码
|
||||
cardInfoJson.put("cert_no", info.getSettAccountIdcardNo());
|
||||
// 持卡人证件有效期类型
|
||||
cardInfoJson.put("cert_validity_type", info.getCertValidityType(info.getSettAccountIdcardEffectEnd()));
|
||||
// 持卡人证件有效期 起始
|
||||
cardInfoJson.put("cert_begin_date", info.getSettAccountIdcardEffectBegin().replace("-", ""));
|
||||
// 持卡人证件有效期 截止
|
||||
if (!"长期".equals(info.getSettAccountIdcardEffectEnd())) {
|
||||
cardInfoJson.put("cert_end_date", info.getSettAccountIdcardEffectEnd().replace("-", ""));
|
||||
}
|
||||
// 结算卡正面
|
||||
// fileJson.put("settle_card_front_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F13", info.getSettAccountLicenseImg(), mchApplyment.getIfCode()));
|
||||
// // 结算卡反面
|
||||
// fileJson.put("settle_card_back_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F14", info.getSettBankCardBackImg(), mchApplyment.getIfCode()));
|
||||
// // 结算人身份证人像面
|
||||
// fileJson.put("settle_cert_front_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F55", info.getSettAccountIdcard1Img(), mchApplyment.getIfCode()));
|
||||
// // 结算人身份证国徽面
|
||||
// fileJson.put("settle_cert_back_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F56", info.getSettAccountIdcard2Img(), mchApplyment.getIfCode()));
|
||||
// // 授权委托书
|
||||
// fileJson.put("auth_enturst_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F15", info.getAuthEnturstPic(), mchApplyment.getIfCode()));
|
||||
//
|
||||
// // 签约人类型
|
||||
// signUserInfoJson.put("type", "LEGAL");
|
||||
} else {
|
||||
cardInfoJson.put("mp", info.getSettAccountBindPhone());
|
||||
// 对私非法人
|
||||
cardInfoJson.put("card_type", "2");
|
||||
// 持卡人证件类型 默认为身份证
|
||||
cardInfoJson.put("cert_type", "00");
|
||||
// 持卡人证件号码
|
||||
cardInfoJson.put("cert_no", info.getSettAccountIdcardNo());
|
||||
// 持卡人证件有效期类型
|
||||
cardInfoJson.put("cert_validity_type", info.getCertValidityType(info.getSettAccountIdcardEffectEnd()));
|
||||
// 持卡人证件有效期 起始
|
||||
cardInfoJson.put("cert_begin_date", info.getSettAccountIdcardEffectBegin().replace("-", ""));
|
||||
// 持卡人证件有效期 截止
|
||||
if (!"长期".equals(info.getSettAccountIdcardEffectEnd())) {
|
||||
cardInfoJson.put("cert_end_date", info.getSettAccountIdcardEffectEnd().replace("-", ""));
|
||||
}
|
||||
// // 结算卡正面
|
||||
// fileJson.put("settle_card_front_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F13", info.getSettAccountLicenseImg(), mchApplyment.getIfCode()));
|
||||
// // 结算卡反面
|
||||
// fileJson.put("settle_card_back_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F14", info.getSettBankCardBackImg(), mchApplyment.getIfCode()));
|
||||
// // 结算人身份证人像面
|
||||
// fileJson.put("settle_cert_front_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F55", info.getSettAccountIdcard1Img(), mchApplyment.getIfCode()));
|
||||
// // 结算人身份证国徽面
|
||||
// fileJson.put("settle_cert_back_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F56", info.getSettAccountIdcard2Img(), mchApplyment.getIfCode()));
|
||||
// // 授权委托书
|
||||
// fileJson.put("auth_enturst_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F15", info.getAuthEnturstPic(), mchApplyment.getIfCode()));
|
||||
// // 签约人法人授权书
|
||||
// fileJson.put("sign_auth_file_id", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F245", info.getSignAuthFileId(), mchApplyment.getIfCode()));
|
||||
//
|
||||
// // 签约人类型
|
||||
// signUserInfoJson.put("type", "OTHER");
|
||||
}
|
||||
// 卡户名
|
||||
cardInfoJson.put("card_name", info.getSettAccountName());
|
||||
// 银行卡号
|
||||
cardInfoJson.put("card_no", info.getSettAccountNo());
|
||||
// 银行所在省
|
||||
cardInfoJson.put("prov_id", info.getSettAccountBankBranchAreaCode().get(0));
|
||||
// 银行所在市
|
||||
cardInfoJson.put("area_id", info.getSettAccountBankBranchAreaCode().get(1));
|
||||
// 银行卡绑定手机号
|
||||
cardInfoJson.put("mp", info.getSettAccountBindPhone());
|
||||
|
||||
param.put("card_info", cardInfoJson.toJSONString());
|
||||
|
||||
JSONArray casArr = new JSONArray();
|
||||
casArr.add(cashConfig);
|
||||
param.put("cash_config", casArr.toJSONString());
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(mchApplyment);
|
||||
|
||||
try {
|
||||
JSONObject applyResp = DgPayKit.request(mchAppConfigContext, param, DgPayKit.MCH_APPLY_MODIFY_URL, mchApplyment.getIfCode());
|
||||
JSONObject applyRespData = applyResp.getJSONObject("data");
|
||||
String code = applyRespData.getString("resp_code");
|
||||
String msg = applyRespData.getString("resp_desc");
|
||||
|
||||
if ("00000000".equals(code)) {
|
||||
// 请求通过
|
||||
String applyNo = applyRespData.getString("apply_no");
|
||||
resultModifyApplyment.setChannelApplyNo(applyNo);
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_SUCCESS);
|
||||
|
||||
return localModifySettlementType(mchDataPair);
|
||||
} else if ("90000000".equals(code)) {
|
||||
String applyNo = applyRespData.getString("apply_no");
|
||||
resultModifyApplyment.setChannelApplyNo(applyNo);
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
|
||||
} else {
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
resultModifyApplyment.setApplyErrorInfo("[" + msg + "]");
|
||||
}
|
||||
|
||||
resultModifyApplyment.setChannelVar1(applyRespData.toJSONString());
|
||||
|
||||
String remark = "斗拱支付结算方式变更已发起";
|
||||
resultModifyApplyment.setRemark(remark);
|
||||
log.info("斗拱支付结算方式变更发起成功");
|
||||
} catch (Exception e) {
|
||||
resultModifyApplyment.setApplyErrorInfo("[" + e.getMessage() + "]");
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
}
|
||||
|
||||
return new MutablePair<>(resultModifyApplyment, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> queryModifyResult(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();
|
||||
|
||||
MchModifyApplyment modifyApplyment = mchDataPair.getLeft();
|
||||
resultModifyApplyment.setModifyApplyId(modifyApplyment.getModifyApplyId());
|
||||
|
||||
MchApplyment mchApplyment = mchDataPair.getValue();
|
||||
|
||||
JSONObject reqParams = new JSONObject();
|
||||
reqParams.put("huifu_id", mchApplyment.getChannelMchNo());
|
||||
reqParams.put("apply_no", modifyApplyment.getChannelApplyNo());
|
||||
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(mchApplyment);
|
||||
|
||||
// 发送请求
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, DgPayKit.MCH_APPLY_QUERY_URL, mchApplyment.getIfCode());
|
||||
|
||||
JSONObject bizData = response.getJSONObject("data");
|
||||
String code = bizData.getString("resp_code");
|
||||
if ("00000000".equals(code)) {
|
||||
String applStatus = bizData.getString("apply_status");
|
||||
if ("Y".equals(applStatus)) {
|
||||
// 审核通过
|
||||
resultModifyApplyment.setChannelVar1(processChannelValue(modifyApplyment.getChannelVar1(), bizData));
|
||||
return handleSuccessCase(modifyApplyment, mchDataPair);
|
||||
}
|
||||
if ("N".equals(applStatus) || "F".equals(applStatus)) {
|
||||
resultModifyApplyment.setChannelVar1(processChannelValue(modifyApplyment.getChannelVar1(), bizData));
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
resultModifyApplyment.setApplyErrorInfo("[" + bizData.getString("note") + "]");
|
||||
|
||||
return new MutablePair<>(resultModifyApplyment, null);
|
||||
}
|
||||
|
||||
if ("P".equals(applStatus)) {
|
||||
// 审核中,需要查询签约状态
|
||||
JSONObject signReqParams = new JSONObject();
|
||||
signReqParams.put("huifu_id", mchApplyment.getChannelMchNo());
|
||||
JSONObject signResp = DgPayKit.request(mchAppConfigContext, signReqParams, DgPayKit.MCH_INFO_QUERY_URL, mchApplyment.getIfCode());
|
||||
JSONObject signRespBizData = signResp.getJSONObject("data");
|
||||
String respCode = signRespBizData.getString("resp_code");
|
||||
|
||||
if ("00000000".equals(respCode)) {
|
||||
JSONArray agreementInfoList = signRespBizData.getJSONArray("agreement_info_list");
|
||||
|
||||
JSONObject item = agreementInfoList.getJSONObject(0);
|
||||
|
||||
String conStat = item.getString("con_stat");
|
||||
|
||||
if ("3".equals(conStat)) {
|
||||
// 待签约
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_WAIT_SIGN);
|
||||
|
||||
return new MutablePair<>(resultModifyApplyment, null);
|
||||
}
|
||||
|
||||
if ("5".equals(conStat)) {
|
||||
// 签约完成
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_FINISH_SIGN);
|
||||
|
||||
return new MutablePair<>(resultModifyApplyment, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mchDataPair;
|
||||
}
|
||||
|
||||
private MutablePair<MchModifyApplyment, MchApplyment> handleSuccessCase(MchModifyApplyment modifyApplyment, MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
switch (modifyApplyment.getModifyApplyType()) {
|
||||
case MchModifyApplyment.MODIFY_TYPE_BASE:
|
||||
return localModifyBase(mchDataPair);
|
||||
case MchModifyApplyment.MODIFY_TYPE_SETTLEMENT:
|
||||
return localModifySettlement(mchDataPair);
|
||||
case MchModifyApplyment.MODIFY_TYPE_SETTLEMENT_TYPE:
|
||||
return localModifySettlementType(mchDataPair);
|
||||
default:
|
||||
return mchDataPair;
|
||||
}
|
||||
}
|
||||
|
||||
private String processChannelValue(String channelVal, JSONObject bizData) {
|
||||
JSONObject channelValJSON = StrUtil.isEmptyIfStr(channelVal) ? new JSONObject() : JSON.parseObject(channelVal);
|
||||
channelValJSON.putAll(bizData);
|
||||
return channelValJSON.toJSONString();
|
||||
}
|
||||
|
||||
protected String getCallbackUrl(String ifCode) {
|
||||
return sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/mchApplyment/notify/" + ifCode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.entity.MchInfo;
|
||||
import com.jeequan.jeepay.core.entity.MchSubInfo;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchWxConfigService;
|
||||
import com.jeequan.jeepay.core.model.applyment.ApplymentSignInfo;
|
||||
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.utils.DateKit;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.db.entity.MchSubInfoEntity;
|
||||
import com.jeequan.jeepay.service.impl.MchSubInfoService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DgpayIsvmchWxConfigService implements IIsvmchWxConfigService {
|
||||
|
||||
@Autowired
|
||||
protected SysConfigService sysConfigService;
|
||||
|
||||
@Autowired
|
||||
private MchSubInfoService mchSubInfoService;
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg configPayBaseUrl(String configBaseUrl, String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg applyModifyMchRate(List<PaywayFee> paywayFeeList, String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String queryConfiguredInfo(String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg configBindAppId(String configAppId, String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg configSubscribeAppId(String configAppId, String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg applyModifyMchShortName(String mchShortName, String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg applyModifyMchAppPublicKey(String appPublicKey, String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplymentSignInfo wxOpenSignInfo(MchApplyment mchApplyment) {
|
||||
|
||||
ApplymentSignInfo result = new ApplymentSignInfo();
|
||||
|
||||
JSONObject suJson = JSON.parseObject(mchApplyment.getSuccResParameter());
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(mchApplyment);
|
||||
// 服务商配置参数
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
DgpayIsvParams isvParams = (DgpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment.getIsvNo(), mchApplyment.getIfCode());
|
||||
|
||||
if (suJson == null || StringUtils.isEmpty(suJson.getString("huifuId"))) {
|
||||
result.setState("查询失败");
|
||||
result.setErrInfo("商户参数为空,该商户还未进件成功");
|
||||
return result;
|
||||
}
|
||||
|
||||
// 微信开通意愿二维码地址
|
||||
result.setSignUrl(isvParams.getWxOpenUrl());
|
||||
result.setImgType(ApplymentSignInfo.IMG_TYPE_QRCONTENT);
|
||||
// 请求参数
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 汇付ID
|
||||
reqParams.put("huifu_id", suJson.getString("huifuId"));
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis() + "");
|
||||
|
||||
// 发送请求
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/merchant/busi/realname/query", mchApplyment.getIfCode());
|
||||
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis() + "_info");
|
||||
// 商户详情is_open_small_flag -> 0
|
||||
JSONObject mchInfoData = DgPayKit.request(mchAppConfigContext, reqParams, "/merchant/basicdata/query", mchApplyment.getIfCode()).getJSONObject("data");
|
||||
|
||||
String respCode = mchInfoData.getString("resp_code");
|
||||
String respDesc = mchInfoData.getString("resp_desc");
|
||||
|
||||
if (!respCode.equals("00000000")) {
|
||||
result.setState("获取子商户状态异常");
|
||||
result.setErrInfo("【" + respDesc + "】");
|
||||
result.setImgType("qrContent");
|
||||
result.setSignUrl(isvParams.getAliChannelExtUrl());
|
||||
return result;
|
||||
}
|
||||
|
||||
String feeConfig = "";
|
||||
JSONArray wxConfList = mchInfoData.getJSONArray("qry_wx_conf_list");
|
||||
JSONArray aliConfList = mchInfoData.getJSONArray("qry_ali_conf_list");
|
||||
JSONObject unionConf = mchInfoData.getJSONObject("qry_union_conf");
|
||||
JSONObject bankCardConf = mchInfoData.getJSONObject("qry_bank_card_conf");
|
||||
log.info("【商户信息】微信配置:{}, 支付宝配置:{}, 银联配置:{}, 银行卡配置:{}", wxConfList, aliConfList, unionConf, bankCardConf);
|
||||
|
||||
if (!CollUtil.isEmpty(wxConfList)) {
|
||||
feeConfig = "【微信费率配置成功】";
|
||||
}
|
||||
if (!CollUtil.isEmpty(aliConfList)) {
|
||||
feeConfig = feeConfig + "【支付宝费率配置成功】";
|
||||
}
|
||||
if (!CollUtil.isEmpty(unionConf)) {
|
||||
feeConfig = feeConfig + "【银联费率配置成功】";
|
||||
}
|
||||
if (!CollUtil.isEmpty(bankCardConf)) {
|
||||
feeConfig = feeConfig + "【银行卡支付配置成功】";
|
||||
}
|
||||
|
||||
for (int wxIndex = 0; wxIndex < wxConfList.size(); wxIndex++) {
|
||||
JSONArray aliMerInfos = wxConfList.getJSONObject(wxIndex).getJSONArray("wx_mer_infos");
|
||||
|
||||
if (!CollUtil.isEmpty(aliMerInfos)) {
|
||||
|
||||
for (int i = 0; i < aliMerInfos.size(); i++) {
|
||||
JSONObject item = aliMerInfos.getJSONObject(i);
|
||||
// 支付宝子商户号存在时
|
||||
MchSubInfoEntity wxSubInfo = new MchSubInfoEntity();
|
||||
wxSubInfo.setMchApplyId(mchApplyment.getApplyId());
|
||||
|
||||
String payChannelId = item.getString("pay_channel_id");
|
||||
String bankMerCode = item.getString("bank_mer_code");
|
||||
if (Objects.equals(isvParams.getChannelNo(), payChannelId)) {
|
||||
wxSubInfo.setMainUse(1);
|
||||
result.setChannelSubMchId(bankMerCode);
|
||||
} else {
|
||||
wxSubInfo.setMainUse(0);
|
||||
}
|
||||
wxSubInfo.setSubMchWay("DG");
|
||||
wxSubInfo.setChannelMchNo(mchApplyment.getChannelMchNo());
|
||||
wxSubInfo.setChannelId(payChannelId);
|
||||
wxSubInfo.setAuthStatus(MchSubInfo.AUTH_STATUS_UNAUTHORIZED);
|
||||
wxSubInfo.setSubMchId(bankMerCode);
|
||||
wxSubInfo.setSubMchType("WX");
|
||||
// 此处取1为正常
|
||||
wxSubInfo.setStatus("1");
|
||||
wxSubInfo.setExt(item);
|
||||
|
||||
try {
|
||||
mchSubInfoService.save(wxSubInfo);
|
||||
} catch (DuplicateKeyException e) {
|
||||
log.info("子商户信息已存储过");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.setOriginData(feeConfig);
|
||||
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
// 驳回原因
|
||||
String rejectMsg = resData.getString("reject_reason");
|
||||
|
||||
// 请求异常
|
||||
if (!DgPayKit.STATE_SUCCESS.equals(code)) {
|
||||
result.setErrInfo(resData.getString("resp_desc"));
|
||||
return result;
|
||||
}
|
||||
|
||||
// 申请单状态
|
||||
String applymentStat = resData.getString("applyment_stat");
|
||||
// 授权状态
|
||||
String authorizeStat = resData.getString("authorize_stat");
|
||||
|
||||
// // 小程序码
|
||||
// result.setSignUrl(resData.getString("qrcode_data"));
|
||||
|
||||
LambdaUpdateChainWrapper<MchSubInfoEntity> stateUpdate = mchSubInfoService.lambdaUpdate()
|
||||
.eq(MchSubInfoEntity::getMchApplyId, mchApplyment.getApplyId())
|
||||
.eq(MchSubInfoEntity::getMainUse, 1)
|
||||
.eq(MchSubInfoEntity::getSubMchType, "WX");
|
||||
// 覆写状态
|
||||
if (StringUtils.isNotEmpty(authorizeStat)) {
|
||||
if ("0".equals(authorizeStat)) {
|
||||
stateUpdate.set(MchSubInfoEntity::getAuthStatus, MchSubInfo.AUTH_STATUS_UNAUTHORIZED).update();
|
||||
result.setState("未授权");
|
||||
} else if ("1".equals(authorizeStat)) {
|
||||
result.setState("已授权"); // 覆写状态 , 其他不考虑
|
||||
stateUpdate.set(MchSubInfoEntity::getAuthStatus, MchSubInfo.AUTH_STATUS_AUTHORIZED).update();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.mch.ChannelMchRq;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.settle.ChannelSettleRq;
|
||||
import com.jeequan.jeepay.db.entity.SettleInfo;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractMchApiService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @author crystal
|
||||
* @date 2023/12/4 10:47
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DgpayMchApiService extends AbstractMchApiService<DgpayIsvParams> {
|
||||
|
||||
@Autowired
|
||||
private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.DGPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preCheck() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param applyment
|
||||
* @param mchRq
|
||||
* 01-标准费率线上(支持统一进件页面版)
|
||||
* 02-标准费率线下(支持统一进件页面版)
|
||||
* 03-非盈利行业费率
|
||||
* 04-缴费行业费率
|
||||
* 05-保险行汪费率
|
||||
* 06-行业(蓝海绿洲)活动场景费率
|
||||
* 07-校园餐饮费率
|
||||
* 08-K12中小幼费率
|
||||
* 09-非在线教培行业费率
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChannelRetMsg appidAndPath(MchApplyment applyment, ChannelMchRq mchRq) {
|
||||
JSONObject bizData = new JSONObject();
|
||||
bizData.put("req_seq_id", getIfCode() + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN));
|
||||
bizData.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
bizData.put("huifu_id",applyment.getChannelMchNo());
|
||||
if(ChannelMchRq.Type.PATH.getType().equals(mchRq.getType())){
|
||||
bizData.put("wx_woa_path",mchRq.getJsapiPath());
|
||||
}else if(ChannelMchRq.Type.PUBLIC.getType().equals(mchRq.getType())){
|
||||
bizData.put("wx_woa_app_id",mchRq.getAppid());
|
||||
}else if(ChannelMchRq.Type.APPLET.getType().equals(mchRq.getType())){
|
||||
bizData.put("wx_applet_app_id",mchRq.getAppid());
|
||||
}
|
||||
//默认写死 还不知道作用是什么 传线下
|
||||
bizData.put("fee_type","02");
|
||||
|
||||
DgpayIsvParams isvParams = ((DgpayIsvParams) configContextQueryService.queryIsvParams(applyment));
|
||||
JSONObject respBizData = DgPayKit.req(DgPayKit.MCH_BUSI_CONFIG_URL, isvParams, bizData);
|
||||
ChannelRetMsg retMsg = new ChannelRetMsg();
|
||||
retMsg.setChannelBizData(respBizData);
|
||||
retMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
return retMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 斗拱结算信息查询接口
|
||||
* @param settleRq
|
||||
* @param isvNo
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<JSONObject> querySettleInfo(ChannelSettleRq settleRq, String isvNo, DgpayIsvParams isvParams) {
|
||||
if(StringUtils.isBlank(settleRq.getMercNo())){
|
||||
throw new BizException("缺失商户号");
|
||||
}
|
||||
JSONObject bizData = new JSONObject();
|
||||
bizData.put("req_seq_id",getIfCode() + DateUtil.format(new DateTime(),DatePattern.PURE_DATETIME_MS_FORMATTER));
|
||||
bizData.put("req_date",DateUtil.format(new DateTime(),DatePattern.PURE_DATE_PATTERN));
|
||||
bizData.put("huifu_id",settleRq.getMercNo());
|
||||
bizData.put("begin_date",DateUtil.format(settleRq.getStartDate(),DatePattern.PURE_DATE_PATTERN));
|
||||
bizData.put("end_date",DateUtil.format(settleRq.getEndDate(),DatePattern.PURE_DATE_PATTERN));
|
||||
bizData.put("page_num",settleRq.getPage());
|
||||
bizData.put("page_size",settleRq.getSize());
|
||||
JSONObject respBizData = DgPayKit.req(DgPayKit.MCH_BUSI_SETTLE_QUERY_URL, isvParams, bizData);
|
||||
JSONArray infos = respBizData.getJSONArray("trans_log_result_list");
|
||||
if(infos == null || infos.isEmpty()){
|
||||
return null;
|
||||
}
|
||||
List<JSONObject> result = new ArrayList<>(infos.size());
|
||||
infos.forEach(item -> {
|
||||
JSONObject itemData = ((JSONObject) item);
|
||||
JSONObject stlData = new JSONObject();
|
||||
stlData.put("billNo",itemData.getString("trans_id"));
|
||||
stlData.put("isvNo", isvNo);
|
||||
stlData.put("settleDate",DateUtil.format(DateUtil.parse(itemData.getString("trans_date"),DatePattern.PURE_DATE_PATTERN),DatePattern.NORM_DATE_PATTERN));
|
||||
stlData.put("accountNo",itemData.getString("card_no"));
|
||||
stlData.put("accountName",itemData.getString("card_name"));
|
||||
stlData.put("settleAmt",itemData.getBigDecimal("trans_amt").multiply(BigDecimal.valueOf(100)).longValue());
|
||||
// long feeAmt = itemData.getBigDecimal("fee_amt").multiply(BigDecimal.valueOf(100)).longValue();
|
||||
// if( feeAmt > 0L){
|
||||
// stlData.put("fee",feeAmt);
|
||||
// }
|
||||
stlData.put("remark",itemData.getString("settle_desc"));
|
||||
SettleState val = SettleState.getVal(itemData.getString("trans_stat"));
|
||||
switch (val){
|
||||
case PAY_SUCCESS:
|
||||
stlData.put("state", SettleInfo.SUCCESS);
|
||||
break;
|
||||
case PAY_FAIL:
|
||||
stlData.put("state", SettleInfo.FAIL);
|
||||
break;
|
||||
case PAY_PROGRESS:
|
||||
stlData.put("state", SettleInfo.PROGRESS);
|
||||
break;
|
||||
}
|
||||
stlData.put("channelState",val.getState());
|
||||
result.add(stlData);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum SettleState{
|
||||
|
||||
PAY_PROGRESS("I","付款中"),
|
||||
|
||||
PAY_SUCCESS("S","付款成功"),
|
||||
|
||||
PAY_FAIL("F","付款失败");
|
||||
|
||||
private final String state;
|
||||
|
||||
private final String desc;
|
||||
|
||||
public static SettleState getVal(String state){
|
||||
SettleState[] values = values();
|
||||
for (SettleState val:values) {
|
||||
if(val.getState().equals(state)){
|
||||
return val;
|
||||
}
|
||||
}
|
||||
return PAY_PROGRESS;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,815 @@
|
||||
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.entity.MchInfo;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchApplymentService;
|
||||
import com.jeequan.jeepay.core.model.DBApplicationConfig;
|
||||
import com.jeequan.jeepay.core.model.applyment.ApplymentSignInfo;
|
||||
import com.jeequan.jeepay.core.model.applyment.DgpayApplymentInfo;
|
||||
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.oauth2.WxpayOauth2Params;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvsubMchParams;
|
||||
import com.jeequan.jeepay.core.utils.DateKit;
|
||||
import com.jeequan.jeepay.core.utils.JsonKit;
|
||||
import com.jeequan.jeepay.service.impl.RateConfigService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.utils.DgUtils;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 斗拱接口进件
|
||||
*
|
||||
* @author xiaoyu
|
||||
* @date 2022/6/7 10:23
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DgpayMchApplymentService implements IIsvmchApplymentService<DgpayApplymentInfo> {
|
||||
|
||||
@Autowired
|
||||
protected SysConfigService sysConfigService;
|
||||
|
||||
@Autowired
|
||||
private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Autowired
|
||||
private RateConfigService rateConfigService;
|
||||
|
||||
@Override
|
||||
public MchApplyment firstApplyment(MchApplyment mchApplyment) {
|
||||
// 直接丢到异步处理进件逻辑, 通用请求可照此逻辑
|
||||
MchApplyment result = new MchApplyment();
|
||||
result.setApplyId(mchApplyment.getApplyId());
|
||||
result.setState(com.jeequan.jeepay.core.entity.MchApplyment.STATE_AUDITING_WAIT);
|
||||
result.setRemainStep((byte) 1);
|
||||
|
||||
DgpayApplymentInfo applymentInfo = JSON.parseObject(mchApplyment.getApplyDetailInfo(), DgpayApplymentInfo.class);
|
||||
result.setSettlementType(applymentInfo.getSettleCycle());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MchApplyment rejectModify(MchApplyment mchApplyment) {
|
||||
String logPrefix = "【斗拱商户进件】";
|
||||
MchApplyment result = new MchApplyment();
|
||||
try {
|
||||
|
||||
// 如果未进件成功执行第一次进件方法
|
||||
String succResParameter = mchApplyment.getSuccResParameter();
|
||||
if (StringUtils.isEmpty(succResParameter)) {
|
||||
return firstApplyment(mchApplyment);
|
||||
}
|
||||
|
||||
JSONObject succJson = JSON.parseObject(succResParameter);
|
||||
String huifuId = succJson.getString("huifuId");
|
||||
// 缺少必要参数 执行第一次进件
|
||||
if (StringUtils.isEmpty(huifuId)) {
|
||||
return firstApplyment(mchApplyment);
|
||||
}
|
||||
|
||||
// 获取支付参数
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(mchApplyment);
|
||||
// 获取详细参数
|
||||
JSONObject reqParams = getApplymentParams(mchApplyment);
|
||||
reqParams.put("huifu_id", huifuId);
|
||||
// 业务处理类型 1:基本信息修改 2:业务开通 3:业务修改 4:审核材料补充(审核材料补充除必填字段外仅需要传入file_info字段)
|
||||
reqParams.put("deal_type", "3");
|
||||
|
||||
// 发送请求
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, DgPayKit.MCH_APPLY_UPDATE_URL, mchApplyment.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
if ("00000000".equals(code)) {
|
||||
// 渠道号
|
||||
String channelOrderNo = resData.getString("apply_no");
|
||||
result.setChannelApplyNo(channelOrderNo);
|
||||
// 进件响应参数
|
||||
result.setChannelVar1(resData.toJSONString());
|
||||
result.setState(MchApplyment.STATE_AUDITING);
|
||||
} else if ("90000000".equals(code)) {
|
||||
result.setState(MchApplyment.STATE_AUDITING);
|
||||
} else {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo(code + "[" + resData.getString("resp_desc") + "]");
|
||||
log.error("{} 请求失败:code={}, msg={}", logPrefix, code, resData.getString("resp_desc"));
|
||||
return result;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo("[" + e.getMessage() + "]");
|
||||
log.error("{} 进件失败:", logPrefix, e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MchApplyment replenishInfo(MchApplyment mchApplyment) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MchApplyment query(MchApplyment mchApplyment) {
|
||||
String logPrefix = "【斗拱商户进件状态查询】";
|
||||
MchApplyment result = new MchApplyment();
|
||||
try {
|
||||
String succResParameter = mchApplyment.getSuccResParameter();
|
||||
JSONObject succJson = JSON.parseObject(succResParameter);
|
||||
String huifuId = succJson.getString("huifuId");
|
||||
// 获取支付参数
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB)
|
||||
.setMchApplyment(mchApplyment);
|
||||
|
||||
// 请求参数
|
||||
JSONObject reqParams = new JSONObject();
|
||||
reqParams.put("huifu_id", huifuId);
|
||||
reqParams.put("apply_no", mchApplyment.getChannelApplyNo());
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis());
|
||||
// 发送请求
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, DgPayKit.MCH_APPLY_QUERY_URL, mchApplyment.getIfCode());
|
||||
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
if ("00000000".equals(code)) {
|
||||
String applStatus = resData.getString("apply_status");
|
||||
// 入驻状态
|
||||
String regStatus = resData.getString("reg_status");
|
||||
if ("Y".equals(applStatus)) {
|
||||
// 进件查询响应参数
|
||||
// result.setChannelVar1(resData.toJSONString());
|
||||
// 更新错误信息
|
||||
result.setApplyErrorInfo("");
|
||||
result.setState(MchApplyment.STATE_WAIT_SIGN);
|
||||
if ("S".equals(regStatus)) {
|
||||
// 入驻成功
|
||||
// result.setChannelVar2(resData.toJSONString());
|
||||
result.setState(MchApplyment.STATE_SUCCESS);
|
||||
result.setChannelMchNo(huifuId);
|
||||
|
||||
// 参数重写 商户号+绑卡序列号
|
||||
queryMchInfo(result, mchAppConfigContext, huifuId, mchApplyment.getIfCode());
|
||||
|
||||
} else {
|
||||
result.setApplyErrorInfo(code + "[" + resData.getString("apply_reason") + "]");
|
||||
}
|
||||
} else if ("P".equals(applStatus)) {
|
||||
if ("S".equals(regStatus)) {
|
||||
result.setState(MchApplyment.STATE_WAIT_SIGN);
|
||||
} else {
|
||||
result.setState(MchApplyment.STATE_AUDITING);
|
||||
}
|
||||
} else {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo(code + "[" + resData.getString("apply_reason") + "]");
|
||||
}
|
||||
} else if ("90000000".equals(code)) {
|
||||
result.setState(MchApplyment.STATE_AUDITING);
|
||||
} else {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo(code + "[" + resData.getString("resp_desc") + "]");
|
||||
log.error("{} 请求失败:code={}, msg={}", logPrefix, code, resData.getString("resp_desc"));
|
||||
return result;
|
||||
}
|
||||
|
||||
} catch (BizException e) {
|
||||
result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
result.setApplyErrorInfo("[" + e.getMessage() + "]");
|
||||
log.error("{} 进件失败:", logPrefix, e);
|
||||
} catch (Exception e) {
|
||||
log.info("未知异常", e);
|
||||
throw new BizException(e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplymentSignInfo signInfo(MchApplyment mchApplyment) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public JSONObject getApplymentParams(MchApplyment mchApplyment) {
|
||||
// 获取支付参数
|
||||
DgpayIsvParams isvParams = (DgpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);
|
||||
// 获取详细参数
|
||||
DgpayApplymentInfo info = JSON.parseObject(mchApplyment.getApplyDetailInfo(), DgpayApplymentInfo.class);
|
||||
// 请求参数
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 文件信息
|
||||
JSONObject fileJson = new JSONObject();
|
||||
|
||||
// 认证信息
|
||||
JSONObject realNameInfoJson = new JSONObject();
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 业务申请编号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis());
|
||||
// 渠道商户号
|
||||
reqParams.put("upper_huifu_id", isvParams.getSysId());
|
||||
// ONLINE:线上场景,OFFLINE:线下场景,ALL线上线下 场景类型
|
||||
reqParams.put("scene_type", "1".equals(isvParams.getPayScene()) ? "OFFLINE" : "ONLINE");
|
||||
|
||||
// 实名认证类型
|
||||
realNameInfoJson.put("realname_info_type", "AW");
|
||||
// 支付场景 -- 线下场景
|
||||
realNameInfoJson.put("pay_scene", "1");
|
||||
|
||||
if (CollUtil.isEmpty(info.getAreaCode())) {
|
||||
throw new BizException("请选择店铺经营省市区地址");
|
||||
}
|
||||
|
||||
boolean bankAllow = DgUtils.checkBankLimitArea(info.getAreaCode().getString(0));
|
||||
|
||||
// 经营地址 省
|
||||
reqParams.put("prov_id", info.getAreaCode().get(0));
|
||||
// 经营地址 市
|
||||
reqParams.put("area_id", info.getAreaCode().get(1));
|
||||
// 经营地址 区
|
||||
reqParams.put("district_id", info.getAreaCode().get(2));
|
||||
// 详细经营地址
|
||||
reqParams.put("detail_addr", info.getAddress());
|
||||
|
||||
// 签约人
|
||||
JSONObject signUserInfoJson = new JSONObject();
|
||||
// 签约人类型
|
||||
signUserInfoJson.put("type", "LEGAL");
|
||||
|
||||
// 异步通知地址
|
||||
String notifyUrl = sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/mchApplyment/notify/" + CS.IF_CODE.DGPAY;
|
||||
reqParams.put("async_return_url", notifyUrl);
|
||||
reqParams.put("busi_async_return_url", notifyUrl);
|
||||
// 是否发送短信通知到商户 设置为发送
|
||||
reqParams.put("sms_send_flag", "A");
|
||||
|
||||
// 卡信息
|
||||
JSONObject cardInfoJson = new JSONObject();
|
||||
String settAccountType = info.getSettAccountType();
|
||||
if ("B".equals(settAccountType)) {
|
||||
// 对公
|
||||
cardInfoJson.put("card_type", "0");
|
||||
// 持卡人证件类型 默认为身份证
|
||||
cardInfoJson.put("cert_type", "");
|
||||
// 银行编码
|
||||
cardInfoJson.put("bank_code", info.getBankCode());
|
||||
// 联行号
|
||||
cardInfoJson.put("branch_code", info.getBranchCode());
|
||||
// 支行名称
|
||||
cardInfoJson.put("branch_name", info.getBranchName());
|
||||
|
||||
// 签约人类型
|
||||
signUserInfoJson.put("type", "LEGAL");
|
||||
|
||||
} else if ("C".equals(settAccountType)) {
|
||||
// 对私
|
||||
cardInfoJson.put("card_type", "1");
|
||||
// 持卡人证件类型 默认为身份证
|
||||
cardInfoJson.put("cert_type", "00");
|
||||
// 持卡人证件号码
|
||||
cardInfoJson.put("cert_no", info.getSettAccountIdcardNo());
|
||||
// 持卡人证件有效期类型
|
||||
cardInfoJson.put("cert_validity_type", info.getCertValidityType(info.getSettAccountIdcardEffectEnd()));
|
||||
// 持卡人证件有效期 起始
|
||||
cardInfoJson.put("cert_begin_date", info.getSettAccountIdcardEffectBegin().replace("-", ""));
|
||||
// 持卡人证件有效期 截止
|
||||
if (!"长期".equals(info.getSettAccountIdcardEffectEnd())) {
|
||||
cardInfoJson.put("cert_end_date", info.getSettAccountIdcardEffectEnd().replace("-", ""));
|
||||
}
|
||||
// 结算卡正面
|
||||
fileJson.put("settle_card_front_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F13", info.getSettAccountLicenseImg(), mchApplyment.getIfCode()));
|
||||
// 结算卡反面
|
||||
fileJson.put("settle_card_back_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F14", info.getSettBankCardBackImg(), mchApplyment.getIfCode()));
|
||||
// 结算人身份证人像面
|
||||
fileJson.put("settle_cert_front_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F55", info.getSettAccountIdcard1Img(), mchApplyment.getIfCode()));
|
||||
// 结算人身份证国徽面
|
||||
fileJson.put("settle_cert_back_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F56", info.getSettAccountIdcard2Img(), mchApplyment.getIfCode()));
|
||||
// 授权委托书
|
||||
fileJson.put("auth_enturst_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F15", info.getAuthEnturstPic(), mchApplyment.getIfCode()));
|
||||
|
||||
// 签约人类型
|
||||
signUserInfoJson.put("type", "LEGAL");
|
||||
} else {
|
||||
// 对私非法人
|
||||
cardInfoJson.put("card_type", "2");
|
||||
// 持卡人证件类型 默认为身份证
|
||||
cardInfoJson.put("cert_type", "00");
|
||||
// 持卡人证件号码
|
||||
cardInfoJson.put("cert_no", info.getSettAccountIdcardNo());
|
||||
// 持卡人证件有效期类型
|
||||
cardInfoJson.put("cert_validity_type", info.getCertValidityType(info.getSettAccountIdcardEffectEnd()));
|
||||
// 持卡人证件有效期 起始
|
||||
cardInfoJson.put("cert_begin_date", info.getSettAccountIdcardEffectBegin().replace("-", ""));
|
||||
// 持卡人证件有效期 截止
|
||||
if (!"长期".equals(info.getSettAccountIdcardEffectEnd())) {
|
||||
cardInfoJson.put("cert_end_date", info.getSettAccountIdcardEffectEnd().replace("-", ""));
|
||||
}
|
||||
// 结算卡正面
|
||||
fileJson.put("settle_card_front_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F13", info.getSettAccountLicenseImg(), mchApplyment.getIfCode()));
|
||||
// 结算卡反面
|
||||
fileJson.put("settle_card_back_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F14", info.getSettBankCardBackImg(), mchApplyment.getIfCode()));
|
||||
// 结算人身份证人像面
|
||||
fileJson.put("settle_cert_front_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F55", info.getSettAccountIdcard1Img(), mchApplyment.getIfCode()));
|
||||
// 结算人身份证国徽面
|
||||
fileJson.put("settle_cert_back_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F56", info.getSettAccountIdcard2Img(), mchApplyment.getIfCode()));
|
||||
// 授权委托书
|
||||
fileJson.put("auth_enturst_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F15", info.getAuthEnturstPic(), mchApplyment.getIfCode()));
|
||||
// 签约人法人授权书
|
||||
fileJson.put("sign_auth_file_id", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F245", info.getSignAuthFileId(), mchApplyment.getIfCode()));
|
||||
|
||||
// 签约人类型
|
||||
signUserInfoJson.put("type", "OTHER");
|
||||
}
|
||||
// 卡户名
|
||||
cardInfoJson.put("card_name", info.getSettAccountName());
|
||||
// 银行卡号
|
||||
cardInfoJson.put("card_no", info.getSettAccountNo());
|
||||
// 银行所在省
|
||||
cardInfoJson.put("prov_id", info.getSettAccountBankBranchAreaCode().get(0));
|
||||
// 银行所在市
|
||||
cardInfoJson.put("area_id", info.getSettAccountBankBranchAreaCode().get(1));
|
||||
// 银行卡绑定手机号
|
||||
cardInfoJson.put("mp", info.getSettAccountBindPhone());
|
||||
// 结算卡信息
|
||||
reqParams.put("card_info", cardInfoJson);
|
||||
// 结算配置
|
||||
JSONObject settConfig = new JSONObject();
|
||||
// 结算周期
|
||||
settConfig.put("settle_cycle", info.getSettleCycle());
|
||||
// 起结金额
|
||||
settConfig.put("min_amt", "0.00");
|
||||
// 留存金额
|
||||
settConfig.put("remained_amt", "0.00");
|
||||
|
||||
|
||||
if ("D1".equals(info.getSettleCycle())) {
|
||||
// D1费率 [0.00 - 100.00]
|
||||
|
||||
List<PaywayFee> paywayFeeList = info.getPaywayFeeList();
|
||||
for (PaywayFee paywayFee : paywayFeeList) {
|
||||
if (CS.PAY_WAY_CODE.D1.equals(paywayFee.getWayCode())) {
|
||||
settConfig.put("fixed_ratio", DgpayApplymentInfo.convertRate(paywayFee.getFeeRate()));
|
||||
}
|
||||
}
|
||||
|
||||
settConfig.put("fixed_ratio", isvParams.getSettleFee());
|
||||
// D1结算协议图片文件
|
||||
if (StringUtils.isNotEmpty(info.getSettleAgreePic())) {
|
||||
fileJson.put("settle_agree_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F116", info.getSettleAgreePic(), mchApplyment.getIfCode()));
|
||||
}
|
||||
}
|
||||
reqParams.put("settle_config", settConfig.toJSONString());
|
||||
// 取现配置
|
||||
if (!"0".equals(isvParams.getMchSettManual())) {
|
||||
JSONObject cashJson = new JSONObject();
|
||||
// 取现类型
|
||||
cashJson.put("cash_type", isvParams.getMchSettManual());
|
||||
if (StringUtils.isNotEmpty(isvParams.getCashFee())) {
|
||||
cashJson.put("fee_rate", isvParams.getCashFee());
|
||||
} else {
|
||||
cashJson.put("fix_amt", "0.00");
|
||||
cashJson.put("fee_rate", "0.00");
|
||||
}
|
||||
JSONArray casArr = new JSONArray();
|
||||
casArr.add(cashJson);
|
||||
reqParams.put("cash_config", casArr.toJSONString());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(info.getLoginUserName())) {
|
||||
// 管理员账号
|
||||
reqParams.put("login_name", info.getLoginUserName().trim());
|
||||
}
|
||||
|
||||
// 所属行业MCC
|
||||
reqParams.put("mcc", info.getMccCode());
|
||||
|
||||
// 个人商户
|
||||
if (info.getMerchantType() == 1) {
|
||||
// 个人商户
|
||||
reqParams.put("ent_type", "0");
|
||||
// 商户名
|
||||
reqParams.put("reg_name", info.getContactName());
|
||||
// 商户简称
|
||||
reqParams.put("short_name", info.getMchFullName());
|
||||
JSONObject contactInfoJson = new JSONObject();
|
||||
// 联系人姓名
|
||||
contactInfoJson.put("contact_name", info.getContactName());
|
||||
// 联系人手机号
|
||||
contactInfoJson.put("contact_mobile_no", info.getContactPhone());
|
||||
// 联系人邮箱
|
||||
contactInfoJson.put("contact_email", info.getContactEmail());
|
||||
// 联系人身份证号
|
||||
contactInfoJson.put("contact_cert_no", info.getContactIdcardNo());
|
||||
// 联系人信息
|
||||
reqParams.put("contact_info", contactInfoJson);
|
||||
// 签约人手机号
|
||||
signUserInfoJson.put("sign_mobile_no", info.getContactPhone());
|
||||
// 签约人姓名
|
||||
signUserInfoJson.put("name", info.getContactName());
|
||||
// 签约人手机号
|
||||
signUserInfoJson.put("mobile_no", info.getContactPhone());
|
||||
// 签约人身份证号
|
||||
signUserInfoJson.put("cert_no", info.getContactIdcardNo());
|
||||
// TODO **** 兼容 旧接口 ****
|
||||
// 签约人姓名
|
||||
signUserInfoJson.put("sign_name", info.getContactName());
|
||||
// 签约人身份证号
|
||||
signUserInfoJson.put("sign_cert_no", info.getContactIdcardNo());
|
||||
|
||||
reqParams.put("sign_user_info", signUserInfoJson);
|
||||
|
||||
// 联系人姓名
|
||||
realNameInfoJson.put("name", info.getContactName());
|
||||
// 联系人手机号
|
||||
realNameInfoJson.put("mobile", info.getContactPhone());
|
||||
// 联系人证件号
|
||||
realNameInfoJson.put("contact_id_card_number", info.getContactIdcardNo());
|
||||
|
||||
// 法人身份证人像面照片
|
||||
fileJson.put("identification_front_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F40", info.getIdcard1Img(), mchApplyment.getIfCode()));
|
||||
// 法人身份证国徽面照片
|
||||
fileJson.put("identification_back_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F41", info.getIdcard2Img(), mchApplyment.getIfCode()));
|
||||
|
||||
} else {
|
||||
// 公司类型
|
||||
reqParams.put("ent_type", info.getEntType());
|
||||
// 商户名称
|
||||
reqParams.put("reg_name", info.getMchFullName());
|
||||
// 商户英文名称
|
||||
reqParams.put("mer_en_name", info.getMerEnName());
|
||||
// 经营名称
|
||||
reqParams.put("short_name", info.getMchShortName());
|
||||
// 小票名称
|
||||
reqParams.put("receipt_name", info.getReceiptName());
|
||||
// 经营类型
|
||||
reqParams.put("busi_type", info.getBusiType());
|
||||
// 注册资本
|
||||
reqParams.put("reg_capital", info.getRegCapital());
|
||||
|
||||
// 执照类型 NATIONAL_LEGAL-营业执照 NATIONAL_LEGAL_MERGE-多证合一
|
||||
reqParams.put("license_type", "NATIONAL_LEGAL");
|
||||
// 营业执照编号
|
||||
reqParams.put("license_code", info.getLicenseNo());
|
||||
// 经营范围
|
||||
reqParams.put("business_scope", info.getLicenseBusiness());
|
||||
|
||||
// 营业执照有效期类型
|
||||
reqParams.put("license_validity_type", info.getCertValidityType(info.getLicenseEffectEnd()));
|
||||
// 营业执照有效期开始日期
|
||||
reqParams.put("license_begin_date", info.getLicenseEffectBegin().replace("-", ""));
|
||||
// 营业执照有效期截止日期
|
||||
if (!"长期".equals(info.getLicenseEffectEnd())) {
|
||||
reqParams.put("license_end_date", info.getLicenseEffectEnd().replace("-", ""));
|
||||
}
|
||||
|
||||
JSONObject contactInfoJson = new JSONObject();
|
||||
// 联系人姓名
|
||||
contactInfoJson.put("contact_name", info.getIdcardName());
|
||||
// 联系人手机号
|
||||
contactInfoJson.put("contact_mobile_no", info.getIdCardPhone());
|
||||
// 联系人邮箱
|
||||
contactInfoJson.put("contact_email", info.getIdCardEmail());
|
||||
// 联系人身份证号
|
||||
contactInfoJson.put("contact_cert_no", info.getIdcardNo());
|
||||
// 联系人信息
|
||||
reqParams.put("contact_info", contactInfoJson);
|
||||
|
||||
// 非法人结算签约人信息
|
||||
if (StringUtils.isNotEmpty(info.getSettAccountType()) && "D".equals(info.getSettAccountType())) {
|
||||
// 签约人手机号
|
||||
signUserInfoJson.put("sign_mobile_no", info.getSettAccountBindPhone());
|
||||
// 签约人姓名
|
||||
signUserInfoJson.put("name", info.getSettAccountName());
|
||||
// 签约人手机号
|
||||
signUserInfoJson.put("mobile_no", info.getSettAccountBindPhone());
|
||||
// 签约人身份证号
|
||||
signUserInfoJson.put("cert_no", info.getSettAccountIdcardNo());
|
||||
// TODO **** 兼容 旧接口 ****
|
||||
// 签约人姓名
|
||||
signUserInfoJson.put("sign_name", info.getSettAccountName());
|
||||
// 签约人身份证号
|
||||
signUserInfoJson.put("sign_cert_no", info.getSettAccountIdcardNo());
|
||||
|
||||
} else {
|
||||
// 签约人手机号
|
||||
signUserInfoJson.put("sign_mobile_no", info.getIdCardPhone());
|
||||
signUserInfoJson.put("mobile_no", info.getIdCardPhone());
|
||||
// 签约人姓名
|
||||
signUserInfoJson.put("name", info.getIdcardName());
|
||||
// 签约人身份证号
|
||||
signUserInfoJson.put("cert_no", info.getIdcardNo());
|
||||
|
||||
// TODO **** 兼容 旧接口 ****
|
||||
// 签约人姓名
|
||||
signUserInfoJson.put("sign_name", info.getIdcardName());
|
||||
// 签约人身份证号
|
||||
signUserInfoJson.put("sign_cert_no", info.getIdcardNo());
|
||||
}
|
||||
|
||||
reqParams.put("sign_user_info", signUserInfoJson);
|
||||
|
||||
// 联系人姓名
|
||||
realNameInfoJson.put("name", info.getIdcardName());
|
||||
// 联系人手机号
|
||||
realNameInfoJson.put("mobile", info.getIdCardPhone());
|
||||
// 联系人证件号
|
||||
realNameInfoJson.put("contact_id_card_number", info.getIdcardNo());
|
||||
|
||||
// 注册 省
|
||||
reqParams.put("reg_prov_id", info.getAreaCode().get(0));
|
||||
// 注册 市
|
||||
reqParams.put("reg_area_id", info.getAreaCode().get(1));
|
||||
// 注册 区
|
||||
reqParams.put("reg_district_id", info.getAreaCode().get(2));
|
||||
// 注册地址
|
||||
reqParams.put("reg_detail", info.getAddress());
|
||||
|
||||
// 法人信息
|
||||
JSONObject legalInfoJson = new JSONObject();
|
||||
// 法人姓名
|
||||
legalInfoJson.put("legal_name", info.getIdcardName());
|
||||
// 法人证件类型 默认身份证
|
||||
legalInfoJson.put("legal_cert_type", "00");
|
||||
// 法人证件号码
|
||||
legalInfoJson.put("legal_cert_no", info.getIdcardNo());
|
||||
// 法人手机号
|
||||
legalInfoJson.put("legal_mobile_no", info.getIdCardPhone());
|
||||
// 法人证件居住地
|
||||
legalInfoJson.put("legal_identification_address", info.getIdcardAddress());
|
||||
// 法人证件有效期类型
|
||||
legalInfoJson.put("legal_cert_validity_type", info.getCertValidityType(info.getIdcardEffectEnd()));
|
||||
// 法人证件有效期开始日期
|
||||
legalInfoJson.put("legal_cert_begin_date", info.getIdcardEffectBegin().replace("-", ""));
|
||||
if ("0".equals(info.getCertValidityType(info.getIdcardEffectEnd()))) {
|
||||
// 法人证件有效期截止日期
|
||||
legalInfoJson.put("legal_cert_end_date", info.getIdcardEffectEnd().replace("-", ""));
|
||||
}
|
||||
reqParams.put("legal_info", legalInfoJson);
|
||||
|
||||
// 客服电话
|
||||
reqParams.put("service_phone", info.getServicePhone());
|
||||
|
||||
// 门头照
|
||||
reqParams.put("store_header_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F18", info.getStoreOuterImg(), mchApplyment.getIfCode()));
|
||||
// 内景照
|
||||
reqParams.put("store_indoor_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F19", info.getStoreInnerImg(), mchApplyment.getIfCode()));
|
||||
// 收银台照
|
||||
reqParams.put("store_cashier_desk_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F20", info.getStoreCashierImg(), mchApplyment.getIfCode()));
|
||||
|
||||
// 开户许可证
|
||||
fileJson.put("reg_acct_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F08", info.getCompanyAccountLicenseImg(), mchApplyment.getIfCode()));
|
||||
// 法人身份证人像面照片
|
||||
fileJson.put("legal_cert_front_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F02", info.getIdcard1Img(), mchApplyment.getIfCode()));
|
||||
// 法人身份证国徽面照片
|
||||
fileJson.put("legal_cert_back_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F03", info.getIdcard2Img(), mchApplyment.getIfCode()));
|
||||
// 营业执照
|
||||
fileJson.put("license_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F07", info.getLicenseImg(), mchApplyment.getIfCode()));
|
||||
// 组织机构代码证
|
||||
// fileJson.put("org_code_pic", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F57", info.getOrgCodePic()));
|
||||
// 签约人身份证照片-人像照
|
||||
fileJson.put("sign_identity_front_file_id", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F244", info.getIdcard1Img(), mchApplyment.getIfCode()));
|
||||
// 签约人身份证照片-国徽照
|
||||
fileJson.put("sign_identity_back_file_id", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F247", info.getIdcard2Img(), mchApplyment.getIfCode()));
|
||||
}
|
||||
|
||||
// 扩展资料包
|
||||
JSONArray extendedList = new JSONArray();
|
||||
if (StringUtils.isNotEmpty(info.getServiceAgreement())) {
|
||||
// 【商户】斗拱平台综合支付服务协议(纸质合同版)
|
||||
JSONObject paramJson = JsonKit.newJson("file_id", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F479", info.getServiceAgreement(), mchApplyment.getIfCode()));
|
||||
paramJson.put("file_type", "F479");
|
||||
extendedList.add(paramJson);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(info.getPriceConfirmation())) {
|
||||
// 【商户】斗拱平台综合支付服务功能及价格确认表(纸质合同版)
|
||||
JSONObject paramJson = JsonKit.newJson("file_id", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F480", info.getPriceConfirmation(), mchApplyment.getIfCode()));
|
||||
paramJson.put("file_type", "F480");
|
||||
extendedList.add(paramJson);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(info.getStoreInnerImg())) {
|
||||
// (线上场景)办公场所照片-工作区域
|
||||
JSONObject paramJson = JsonKit.newJson("file_id", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F371", info.getStoreInnerImg(), mchApplyment.getIfCode()));
|
||||
paramJson.put("file_type", "F371");
|
||||
extendedList.add(paramJson);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(info.getStoreOuterImg())) {
|
||||
// (线上场景)办公场所照片-公司前台
|
||||
JSONObject paramJson = JsonKit.newJson("file_id", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F478", info.getStoreOuterImg(), mchApplyment.getIfCode()));
|
||||
paramJson.put("file_type", "F478");
|
||||
extendedList.add(paramJson);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(info.getStoreOuterImg())) {
|
||||
// 门头照
|
||||
JSONObject paramJson = JsonKit.newJson("file_id", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F22", info.getStoreOuterImg(), mchApplyment.getIfCode()));
|
||||
paramJson.put("file_type", "F22");
|
||||
extendedList.add(paramJson);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(info.getStoreInnerImg())) {
|
||||
// 内景照
|
||||
JSONObject paramJson = JsonKit.newJson("file_id", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F24", info.getStoreInnerImg(), mchApplyment.getIfCode()));
|
||||
paramJson.put("file_type", "F24");
|
||||
extendedList.add(paramJson);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(info.getStoreCashierImg())) {
|
||||
// 收银台照
|
||||
JSONObject paramJson = JsonKit.newJson("file_id", DgPayKit.uploadFile(mchApplyment.getIsvNo(), "F105", info.getStoreCashierImg(), mchApplyment.getIfCode()));
|
||||
paramJson.put("file_type", "F105");
|
||||
extendedList.add(paramJson);
|
||||
}
|
||||
|
||||
reqParams.put("extended_material_list", extendedList.toJSONString());
|
||||
|
||||
JSONObject agreementJson = new JSONObject();
|
||||
// 如果配置了协议信息 走电子协议 未配置则纸质协议
|
||||
if (StringUtils.isNotEmpty(isvParams.getAgreementModel())) {
|
||||
// 协议类型
|
||||
agreementJson.put("agreement_type", "0");
|
||||
// 协议模板号
|
||||
agreementJson.put("agreement_model", isvParams.getAgreementModel());
|
||||
// 协议模板名称
|
||||
agreementJson.put("agreement_name", isvParams.getAgreementName());
|
||||
} else {
|
||||
// 协议类型
|
||||
agreementJson.put("agreement_type", "1");
|
||||
}
|
||||
reqParams.put("agreement_info", agreementJson.toJSONString());
|
||||
|
||||
// 业务开关配置
|
||||
JSONObject bizConfJson = new JSONObject();
|
||||
// 延迟入账开关
|
||||
bizConfJson.put("delay_flag", "Y");
|
||||
// 是否开通补贴支付
|
||||
bizConfJson.put("combine_pay_flag", "Y");
|
||||
// 是否开通余额支付
|
||||
bizConfJson.put("balance_pay_flag", "Y");
|
||||
// 是否开通结算
|
||||
bizConfJson.put("settle_flag", "Y");
|
||||
// // 商户开通强制延迟标记
|
||||
// bizConfJson.put("forced_delay_flag", "Y");
|
||||
// // 是否开通网银
|
||||
// bizConfJson.put("online_flag", "Y");
|
||||
// // 是否开通快捷
|
||||
// bizConfJson.put("quick_flag", "Y");
|
||||
// // 是否开通代扣
|
||||
// bizConfJson.put("withhold_flag", "Y");
|
||||
// // 是否开通微信预授权
|
||||
// bizConfJson.put("wechatpay_pre_auth_flag", "Y");
|
||||
// // 是否开通支付宝预授权
|
||||
// bizConfJson.put("alipay_pre_auth_flag", "Y");
|
||||
|
||||
reqParams.put("biz_conf", bizConfJson);
|
||||
|
||||
|
||||
// 支付宝配置对象
|
||||
List<JSONObject> aliPayFeeList = info.convertAliPayFee(isvParams);
|
||||
if (CollUtil.isNotEmpty(aliPayFeeList)) {
|
||||
reqParams.put("ali_conf_list", JSON.toJSONString(aliPayFeeList));
|
||||
}
|
||||
|
||||
WxpayOauth2Params wxpayOauth2Params = (WxpayOauth2Params) configContextQueryService.queryIsvOauth2Params(mchApplyment.getIsvNo(), CS.IF_CODE.WXPAY);
|
||||
DBApplicationConfig dbApplicationConfig = sysConfigService.getDBApplicationConfig();
|
||||
// 微信配置对象
|
||||
List<JSONObject> wxPayFeeList = info.convertWxPayFee(isvParams, wxpayOauth2Params, dbApplicationConfig);
|
||||
if (CollUtil.isNotEmpty(wxPayFeeList)) {
|
||||
reqParams.put("wx_conf_list", JSON.toJSONString(wxPayFeeList));
|
||||
}
|
||||
|
||||
if (bankAllow) {
|
||||
// 银联配置对象
|
||||
List<JSONObject> unionList = info.convertUniPayFee();
|
||||
if (CollUtil.isNotEmpty(unionList)) {
|
||||
reqParams.put("union_conf_list", unionList.toString());
|
||||
}
|
||||
// 银行卡业务配置
|
||||
JSONObject bankPayFee = info.convertBankPayFee();
|
||||
if (bankPayFee != null && bankPayFee.size() > 1) {
|
||||
reqParams.put("bank_card_conf", bankPayFee.toJSONString());
|
||||
}
|
||||
// 银联小微参数配置
|
||||
if (CollUtil.isNotEmpty(unionList)) {
|
||||
reqParams.put("union_micro_info", info.getMicroInfo());
|
||||
}
|
||||
}
|
||||
|
||||
// 文件集
|
||||
reqParams.put("file_info", fileJson);
|
||||
// 实名认证信息
|
||||
reqParams.put("wx_realname_info", realNameInfoJson);
|
||||
|
||||
return reqParams;
|
||||
}
|
||||
|
||||
public void setAccountInfo(MchApplyment mchApplyment, JSONObject reqParams) {
|
||||
DgpayApplymentInfo info = JSON.parseObject(mchApplyment.getApplyDetailInfo(), DgpayApplymentInfo.class);
|
||||
if (info.getMerchantType() == 1) {
|
||||
reqParams.put("name", info.getContactName());
|
||||
// 银行卡绑定手机号
|
||||
reqParams.put("mobile_no", info.getSettAccountBindPhone());
|
||||
// 持卡人证件类型 默认为身份证
|
||||
reqParams.put("cert_type", "00");
|
||||
// 持卡人证件号码
|
||||
reqParams.put("cert_no", info.getSettAccountIdcardNo());
|
||||
// 持卡人证件有效期类型
|
||||
reqParams.put("cert_validity_type", info.getCertValidityType(info.getSettAccountIdcardEffectEnd()));
|
||||
// 持卡人证件有效期 起始
|
||||
reqParams.put("cert_begin_date", info.getSettAccountIdcardEffectBegin().replace("-", ""));
|
||||
// 持卡人证件有效期 截止
|
||||
if (!"长期".equals(info.getSettAccountIdcardEffectEnd())) {
|
||||
reqParams.put("cert_end_date", info.getSettAccountIdcardEffectEnd().replace("-", ""));
|
||||
}
|
||||
} else {
|
||||
// 联系人姓名
|
||||
reqParams.put("contact_name", info.getIdcardName());
|
||||
// 联系人手机号
|
||||
reqParams.put("contact_mobile", info.getIdCardPhone());
|
||||
// 联系人邮箱
|
||||
reqParams.put("contact_email", info.getIdCardEmail());
|
||||
// 联系人身份证号
|
||||
reqParams.put("contact_cert_no", info.getIdcardNo());
|
||||
|
||||
// 法人姓名
|
||||
reqParams.put("legal_name", info.getIdcardName());
|
||||
// 法人证件类型 默认身份证
|
||||
reqParams.put("legal_cert_type", "00");
|
||||
// 法人证件号码
|
||||
reqParams.put("legal_cert_no", info.getIdcardNo());
|
||||
// 法人证件有效期类型
|
||||
reqParams.put("legal_cert_validity_type", info.getCertValidityType(info.getIdcardEffectEnd()));
|
||||
// 法人证件有效期开始日期
|
||||
reqParams.put("legal_cert_begin_date", info.getIdcardEffectBegin().replace("-", ""));
|
||||
if ("0".equals(info.getCertValidityType(info.getIdcardEffectEnd()))) {
|
||||
// 法人证件有效期截止日期
|
||||
reqParams.put("legal_cert_end_date", info.getIdcardEffectEnd().replace("-", ""));
|
||||
}
|
||||
}
|
||||
// 发送短信标识
|
||||
reqParams.put("sms_send_flag", "Y");
|
||||
|
||||
reqParams.remove("area_id");
|
||||
reqParams.remove("detail_addr");
|
||||
reqParams.remove("prov_id");
|
||||
reqParams.remove("district_id");
|
||||
reqParams.remove("busi_type");
|
||||
reqParams.remove("mcc");
|
||||
reqParams.remove("receipt_name");
|
||||
reqParams.remove("ent_type");
|
||||
reqParams.remove("upper_huifu_id");
|
||||
reqParams.put("noMchId", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询商户详细信息
|
||||
**/
|
||||
public void queryMchInfo(MchApplyment result, MchAppConfigContext mchAppConfigContext, String huifuId, String ifCode) {
|
||||
String logPrefix = "【斗拱】查询商户详细信息";
|
||||
try {
|
||||
// 请求参数
|
||||
JSONObject reqParams = new JSONObject();
|
||||
reqParams.put("huifu_id", huifuId);
|
||||
// 发送请求
|
||||
log.info("{}请求开始", logPrefix);
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, DgPayKit.MCH_INFO_QUERY_URL, ifCode);
|
||||
log.info("{}请求结束", logPrefix);
|
||||
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
if ("00000000".equals(code)) {
|
||||
JSONArray infoList = resData.getJSONArray("qry_cash_card_info_list");
|
||||
if (CollUtil.isNotEmpty(infoList)) {
|
||||
// 取第一个卡信息
|
||||
JSONObject infoJson = (JSONObject) JSON.toJSON(infoList.get(0));
|
||||
// 绑卡序列号
|
||||
String tokenNo = infoJson.getString("token_no");
|
||||
DgpayIsvsubMchParams mchParams = new DgpayIsvsubMchParams();
|
||||
mchParams.setHuifuId(huifuId);
|
||||
mchParams.setTokenNo(tokenNo);
|
||||
result.setSuccResParameter(JSON.toJSONString(mchParams));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("{} 异常:", logPrefix, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IPayOrderCloseService;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.utils.DateKit;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单关闭
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2023/2/28 16:30
|
||||
*/
|
||||
@Service
|
||||
public class DgpayPayOrderCloseService implements IPayOrderCloseService {
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg close(PayOrder payOrder, MchAppConfigContext mchAppConfigContext){
|
||||
|
||||
try {
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 请求流水号
|
||||
reqParams.put("req_seq_id", DateKit.currentTimeMillis()+"");
|
||||
// 交易流水号
|
||||
reqParams.put("org_hf_seq_id", payOrder.getChannelOrderNo());
|
||||
// 商户号
|
||||
reqParams.put("huifu_id", payOrder.getChannelMchNo());
|
||||
// 原机构请求日期
|
||||
reqParams.put("org_req_date", DateUtil.format(payOrder.getCreatedAt(), DatePattern.PURE_DATE_PATTERN));
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/trade/payment/scanpay/close", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
//如果查询请求成功
|
||||
if(DgPayKit.STATE_SUCCESS.equals(code)){
|
||||
String transStat = resData.getString("trans_stat");
|
||||
if (DgPayKit.STATE_SUCCESS_S.equals(transStat)) {
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}else if (DgPayKit.STATE_FAIL_F.equals(transStat)) {
|
||||
// 失败
|
||||
return ChannelRetMsg.confirmFail(resData.getString("resp_desc"));
|
||||
}
|
||||
}else if(DgPayKit.STATE_ING.equals(code)) {
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}
|
||||
//支付中
|
||||
return ChannelRetMsg.waiting();
|
||||
}catch (Exception e) {
|
||||
//支付中
|
||||
return ChannelRetMsg.waiting();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IPayOrderQueryService;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 斗拱 查询订单
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/6/9 17:05
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DgpayPayOrderQueryService implements IPayOrderQueryService {
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg query(PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
|
||||
// 智能POS 直接返回
|
||||
if (StringUtils.equals(payOrder.getWayCode(), CS.PAY_WAY_CODE.AUTO_POS)) {
|
||||
return ChannelRetMsg.waiting();
|
||||
}
|
||||
try {
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 交易流水号
|
||||
reqParams.put("mer_ord_id", payOrder.getPayOrderId());
|
||||
// 商户号
|
||||
reqParams.put("huifu_id", payOrder.getChannelMchNo());
|
||||
// 原机构请求日期
|
||||
reqParams.put("org_req_date", DateUtil.format(payOrder.getCreatedAt(), DatePattern.PURE_DATE_PATTERN));
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/trade/payment/scanpay/query", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
//如果查询请求成功
|
||||
if(DgPayKit.STATE_SUCCESS.equals(code)){
|
||||
String tradeState = resData.getString("trans_stat");
|
||||
if (DgPayKit.STATE_SUCCESS_S.equals(tradeState)) {
|
||||
String channelOrderNo = resData.getString("org_hf_seq_id");
|
||||
// 渠道订单号
|
||||
String outTransId = resData.getString("out_trans_id");
|
||||
// 商户订单号
|
||||
String partyOrderId = resData.getString("party_order_id");
|
||||
String drType = CS.DrType.OTHER.getType();
|
||||
String debit_type = resData.getString("debit_type");
|
||||
if("D".equals(debit_type)){
|
||||
drType = CS.DrType.DEBIT.getType();
|
||||
}else if("C".equals(debit_type)){
|
||||
drType = CS.DrType.CREDIT.getType();
|
||||
}
|
||||
return ChannelRetMsg.confirmSuccess(channelOrderNo, outTransId, partyOrderId,drType);
|
||||
}else if (DgPayKit.STATE_FAIL_F.equals(tradeState)) {
|
||||
// 失败
|
||||
return ChannelRetMsg.confirmFail();
|
||||
}
|
||||
}
|
||||
//支付中
|
||||
return ChannelRetMsg.waiting();
|
||||
}catch (Exception e) {
|
||||
//支付中
|
||||
return ChannelRetMsg.waiting();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.PaywayUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* * 支付接口: 斗拱
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/5/13 15:02
|
||||
*/
|
||||
@Service
|
||||
public class DgpayPaymentService extends AbstractPaymentService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.DGPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupport(String wayCode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
return PaywayUtil.getRealPaywayService(this, payOrder.getWayCode()).preCheck(rq, payOrder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
return PaywayUtil.getRealPaywayService(this, payOrder.getWayCode()).pay(rq, payOrder, mchAppConfigContext);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.entity.RefundOrder;
|
||||
import com.jeequan.jeepay.core.exception.ResponseException;
|
||||
import com.jeequan.jeepay.core.model.autopos.ChannelOrderAcceptParams;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractPosNoticeService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 富友智能POS回调
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2021-06-07 07:15
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class DgpayPosNoticeService extends AbstractPosNoticeService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.DGPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Triple<String, String, Object> parseParams(HttpServletRequest request) {
|
||||
|
||||
JSONObject params = getReqParamJSON();
|
||||
|
||||
String respCode = params.getString("resp_code");
|
||||
if (!StringUtils.equals(DgPayKit.STATE_SUCCESS, respCode)) {
|
||||
log.info("汇付斗拱智能POS【订单推送模式】回调处理失败,resp_code={}", respCode);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
|
||||
// 交易数据
|
||||
JSONObject respData = params.getJSONObject("resp_data");
|
||||
String subRespCode = respData.getString("sub_resp_code");
|
||||
if (!StringUtils.equals(DgPayKit.STATE_SUCCESS, subRespCode)) {
|
||||
log.info("汇付斗拱智能POS【订单推送模式】回调处理失败,sub_resp_code={}", subRespCode);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
|
||||
String payOrderId = respData.getString("mer_ord_id");
|
||||
String transType = respData.getString("trans_type"); // TRANS_REFUND: 交易退款 SCAN_REFUND: 终端扫码退款
|
||||
|
||||
String tradeType = "";
|
||||
if (StringUtils.isNotBlank(transType)) {
|
||||
tradeType = ChannelOrderAcceptParams.TRADE_TYPE_PAYMENT;
|
||||
|
||||
if (StringUtils.equalsAny(transType, "TRANS_REFUND", "SCAN_REFUND")) {
|
||||
tradeType = ChannelOrderAcceptParams.TRADE_TYPE_REFUND;
|
||||
}
|
||||
}
|
||||
|
||||
log.info("斗拱智能POS【订单推送模式】通知参数:tradeType={},params={}", tradeType, params.toJSONString());
|
||||
return Triple.of(tradeType, payOrderId, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg payNotice(HttpServletRequest request, Object params, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) {
|
||||
|
||||
String logPrefix = "处理斗拱智能POS【订单推送模式】支付回调";
|
||||
JSONObject jsonParams = (JSONObject) params;
|
||||
|
||||
// 验签
|
||||
validate(jsonParams, mchAppConfigContext, payOrder.getIfCode(), logPrefix);
|
||||
|
||||
// 获取请求参数
|
||||
JSONObject respData = jsonParams.getJSONObject("resp_data");
|
||||
|
||||
String transAmt = AmountUtil.convertDollar2Cent(respData.getString("trans_amt"));
|
||||
if (!String.valueOf(payOrder.getAmount()).equals(transAmt)) {
|
||||
log.error("{} 金额不符,trans_amt={},amount={}", logPrefix, transAmt, payOrder.getAmount());
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
|
||||
// 判断上游订单状态
|
||||
ResponseEntity okResponse = textResp("RECV_ORD_ID_" + payOrder.getPayOrderId());
|
||||
|
||||
ChannelRetMsg result = new ChannelRetMsg();
|
||||
// 默认支付中
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
String transStat = respData.getString("trans_stat"); // 支付状态 I:初始、P:处理中、S:成功、F:失败
|
||||
if(DgPayKit.STATE_SUCCESS_S.equals(transStat)){
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
|
||||
}else if(DgPayKit.STATE_FAIL_F.equals(transStat)){
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}
|
||||
|
||||
result.setResponseEntity(okResponse);
|
||||
result.setChannelOrderId(respData.getString("req_seq_id"));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg refundNotice(HttpServletRequest request, Object params, RefundOrder refundOrder, MchAppConfigContext mchAppConfigContext) {
|
||||
String logPrefix = "处理斗拱智能POS【订单推送模式】退款通知";
|
||||
|
||||
JSONObject jsonParams = (JSONObject) params;
|
||||
|
||||
// 验签
|
||||
validate(jsonParams, mchAppConfigContext, refundOrder.getIfCode(), logPrefix);
|
||||
|
||||
// 获取请求参数
|
||||
JSONObject respData = jsonParams.getJSONObject("resp_data");
|
||||
String transAmt = AmountUtil.convertDollar2Cent(respData.getString("ord_amt"));
|
||||
if (!String.valueOf(refundOrder.getRefundAmount()).equals(transAmt)) {
|
||||
log.error("{} 金额不符,ord_amt={},amount={}", logPrefix, transAmt, refundOrder.getRefundAmount());
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
|
||||
// 判断上游订单状态
|
||||
ResponseEntity okResponse = textResp("RECV_ORD_ID_" + refundOrder.getRefundOrderId());
|
||||
|
||||
ChannelRetMsg result = new ChannelRetMsg();
|
||||
// 默认支付中
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
String transStat = respData.getString("trans_stat"); // 支付状态 I:初始、P:处理中、S:成功、F:失败
|
||||
if(DgPayKit.STATE_SUCCESS_S.equals(transStat)){
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
|
||||
}else if(DgPayKit.STATE_FAIL_F.equals(transStat)){
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}
|
||||
|
||||
result.setResponseEntity(okResponse);
|
||||
result.setChannelOrderId(respData.getString("hf_seq_id"));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验签
|
||||
* @return
|
||||
*/
|
||||
private void validate(JSONObject jsonParams, MchAppConfigContext mchAppConfigContext, String ifCode, String logPrefix) {
|
||||
|
||||
String sign = jsonParams.getString("sign");
|
||||
|
||||
// 公钥参数
|
||||
DgpayIsvParams isvParams = (DgpayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment().getIsvNo(), ifCode);
|
||||
|
||||
// 验证签名
|
||||
boolean verifyResult = DgPayKit.verify(jsonParams.getString("resp_data"), isvParams.getPosPublicKey(), sign);
|
||||
// 验签失败
|
||||
if(!verifyResult){
|
||||
log.error("{} 验签失败", logPrefix);
|
||||
throw ResponseException.buildText("SIGN ERROR");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.entity.RefundOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvsubMchParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRefundLimit;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.refund.RefundOrderRQ;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractRefundService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 退款接口: 斗拱
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/6/9 17:43
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DgpayRefundService extends AbstractRefundService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.DGPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String preCheck(RefundOrderRQ bizRQ, RefundOrder refundOrder, PayOrder payOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg refund(RefundOrderRQ bizRQ, RefundOrder refundOrder, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
|
||||
// 智能pos收款,走独立退款接口
|
||||
if (StringUtils.equals(payOrder.getWayCode(), CS.PAY_WAY_CODE.AUTO_POS)) {
|
||||
return autoPosRefund(bizRQ, refundOrder, payOrder, mchAppConfigContext);
|
||||
}
|
||||
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 交易流水号
|
||||
reqParams.put("req_seq_id", refundOrder.getRefundOrderId());
|
||||
// 原交易请求订单号
|
||||
reqParams.put("org_req_seq_id", payOrder.getPayOrderId());
|
||||
// 商户号
|
||||
reqParams.put("huifu_id", payOrder.getChannelMchNo())
|
||||
;
|
||||
reqParams.put("notify_url", getNotifyUrl());
|
||||
// 请求日期
|
||||
reqParams.put("req_date", DateUtil.format(refundOrder.getCreatedAt(), DatePattern.PURE_DATE_PATTERN));
|
||||
// 退款金额
|
||||
reqParams.put("ord_amt", AmountUtil.convertCent2Dollar(refundOrder.getRefundAmount()));
|
||||
// 原交易请求日期
|
||||
reqParams.put("org_req_date", DateUtil.format(payOrder.getCreatedAt(), DatePattern.PURE_DATE_PATTERN));
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/trade/payment/scanpay/refund", refundOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
// 调用成功
|
||||
if(DgPayKit.STATE_SUCCESS.equals(code)){
|
||||
String tradeState = resData.getString("trans_stat");
|
||||
if (DgPayKit.STATE_SUCCESS_S.equals(tradeState)) {
|
||||
String channelOrderNo = resData.getString("hf_seq_id");
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
return ChannelRetMsg.confirmSuccess(channelOrderNo);
|
||||
}else if (DgPayKit.STATE_FAIL_F.equals(tradeState)) {
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
// 状态失败
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
}
|
||||
}else if (DgPayKit.STATE_ING.equals(code)){
|
||||
return channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
}else{
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
// 状态失败
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
}
|
||||
return channelRetMsg;
|
||||
}
|
||||
|
||||
private ChannelRetMsg autoPosRefund(RefundOrderRQ bizRQ, RefundOrder refundOrder, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) {
|
||||
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
|
||||
// 智能POS bizParams参数
|
||||
JSONObject bizParams = JSONObject.parseObject(payOrder.getChannelBizData());
|
||||
if (bizParams == null || StringUtils.isBlank(bizParams.getString("deviceNo"))) {
|
||||
throw new BizException("该订单不支持接口退款,请在POS机完成退款!");
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// 请求数据data
|
||||
JSONObject dataParams = new JSONObject();
|
||||
dataParams.put("device_id", bizParams.getString("deviceNo"));
|
||||
|
||||
// 退款信息
|
||||
JSONObject jsonData = new JSONObject();
|
||||
jsonData.put("interfaceType", "refund");
|
||||
jsonData.put("channelId", DgPayKit.covertChannelId(bizParams.getString("channelType"))); // 支付渠道
|
||||
jsonData.put("ordAmt", refundOrder.getRefundAmount().toString());
|
||||
jsonData.put("oriOutOrderId", payOrder.getPayOrderId()); // 原三方订单号
|
||||
jsonData.put("outOrdId", refundOrder.getRefundOrderId()); // 外部订单号
|
||||
jsonData.put("bgRetUrl", "virgo://" + getPosNotifyUrl());
|
||||
dataParams.put("json_data", jsonData.toJSONString());
|
||||
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, dataParams, "/trade/cloudmis/device/information", refundOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
|
||||
String code = resData.getString("resp_code");
|
||||
if(!DgPayKit.STATE_SUCCESS.equals(code)){
|
||||
log.error("斗拱智能POS退款失败,错误码:{},错误信息:{}", code, resData.getString("resp_desc"));
|
||||
}
|
||||
|
||||
channelRetMsg.setChannelOrderId(resData.getString("termOrdId"));
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
return channelRetMsg;
|
||||
|
||||
}catch (BizException e) {
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
channelRetMsg.setChannelErrCode(e.getApiRes().getCode()+"");
|
||||
channelRetMsg.setChannelErrMsg(e.getApiRes().getMsg());
|
||||
}catch (Exception e) {
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}
|
||||
return channelRetMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg query(RefundOrder refundOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
if (StringUtils.equals(refundOrder.getWayCode(), CS.PAY_WAY_CODE.AUTO_POS)) {
|
||||
return ChannelRetMsg.waiting();
|
||||
}
|
||||
try {
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
DgpayIsvsubMchParams mchParams = (DgpayIsvsubMchParams)configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getMchApplyment().getAutoConfigMchAppId(), refundOrder.getIfCode());
|
||||
JSONObject reqParams = new JSONObject();
|
||||
// 交易流水号
|
||||
reqParams.put("org_req_seq_id", refundOrder.getRefundOrderId());
|
||||
// 商户号
|
||||
reqParams.put("huifu_id", mchParams.getHuifuId());
|
||||
// 原机构请求日期
|
||||
reqParams.put("org_req_date", DateUtil.format(refundOrder.getCreatedAt(), DatePattern.PURE_DATE_PATTERN));
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/trade/payment/scanpay/refundquery", refundOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
//如果查询请求成功
|
||||
if(DgPayKit.STATE_SUCCESS.equals(code)){
|
||||
String tradeState = resData.getString("trans_stat");
|
||||
if (DgPayKit.STATE_SUCCESS_S.equals(tradeState)) {
|
||||
return ChannelRetMsg.confirmSuccess(null);
|
||||
}else if (DgPayKit.STATE_FAIL_F.equals(tradeState)) {
|
||||
// 失败
|
||||
return ChannelRetMsg.confirmFail();
|
||||
}
|
||||
}
|
||||
//支付中
|
||||
return ChannelRetMsg.waiting();
|
||||
}catch (Exception e) {
|
||||
//支付中
|
||||
return ChannelRetMsg.waiting();
|
||||
}
|
||||
}
|
||||
|
||||
private ChannelRetMsg autoPosQuery(RefundOrder refundOrder, MchAppConfigContext mchAppConfigContext) {
|
||||
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
|
||||
// 智能POS bizParams参数
|
||||
JSONObject bizParams = JSONObject.parseObject(refundOrder.getChannelBizData());
|
||||
if (bizParams == null) {
|
||||
throw new BizException("不支持退款补单");
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// 请求数据data
|
||||
JSONObject dataParams = new JSONObject();
|
||||
dataParams.put("device_id", bizParams.getString("deviceNo"));
|
||||
|
||||
// 退款信息
|
||||
JSONObject jsonData = new JSONObject();
|
||||
jsonData.put("interfaceType", "queryOrder");
|
||||
jsonData.put("tradeNo", refundOrder.getChannelPayOrderNo()); // 外部订单号
|
||||
jsonData.put("outOrdId", refundOrder.getPayOrderId()); // 外部订单号
|
||||
jsonData.put("isSale", "0");
|
||||
jsonData.put("channelId", DgPayKit.covertChannelId(bizParams.getString("channelType")));
|
||||
dataParams.put("json_data ", jsonData.toJSONString());
|
||||
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, dataParams, "/trade/cloudmis/device/information", refundOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
|
||||
String code = resData.getString("resp_code");
|
||||
if(!DgPayKit.STATE_SUCCESS.equals(code)){
|
||||
log.error("斗拱智能POS退款查单失败,错误码:{},错误信息:{}", code, resData.getString("resp_desc"));
|
||||
}
|
||||
|
||||
return channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
|
||||
}catch (BizException e) {
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
channelRetMsg.setChannelErrCode(e.getApiRes().getCode()+"");
|
||||
channelRetMsg.setChannelErrMsg(e.getApiRes().getMsg());
|
||||
}catch (Exception e) {
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}
|
||||
return channelRetMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款权限
|
||||
* @param settleType
|
||||
* @param applyId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChannelRefundLimit isRefundLimit(String settleType,String applyId) {
|
||||
return super.isRefundLimit(settleType,applyId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPlatAccount(RefundOrder refundOrder) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.payway;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliBarOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliBarOrderRS;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgPayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgpayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 斗拱 支付宝 条码支付
|
||||
*
|
||||
* @author pangxiaoyu
|
||||
*
|
||||
* @date 2021/6/8 18:11
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("dgpayPaymentByAliBarService") //Service Name需保持全局唯一性
|
||||
public class AliBar extends DgpayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
|
||||
AliBarOrderRQ bizRQ = (AliBarOrderRQ) rq;
|
||||
if(StringUtils.isEmpty(bizRQ.getAuthCode())){
|
||||
throw new BizException("用户支付条码[authCode]不可为空");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
AliBarOrderRQ bizRQ = (AliBarOrderRQ) rq;
|
||||
AliBarOrderRS res = ApiResBuilder.buildSuccess(AliBarOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
try {
|
||||
JSONObject dataParams = DgPayKit.dataParams(payOrder, getNotifyUrl());
|
||||
dataParams.put("auth_code", bizRQ.getAuthCode());
|
||||
// 设置订单是否需要分账
|
||||
if(isDivisionOrder(payOrder)) {
|
||||
dataParams.put("delay_acct_flag", "Y");
|
||||
}
|
||||
|
||||
JSONObject response = DgPayKit.payRequest(mchAppConfigContext, dataParams, "/trade/payment/micropay", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
channelRetMsg.setChannelBizData(resData);
|
||||
String code = resData.getString("resp_code");
|
||||
if(DgPayKit.STATE_SUCCESS.equals(code)){
|
||||
String transStat = resData.getString("trans_stat");
|
||||
String channelOrderNo = resData.get("hf_seq_id").toString();
|
||||
String debit_type = resData.getString("debit_type");
|
||||
if(StringUtils.isEmpty(debit_type) || "0".equals(debit_type)){
|
||||
channelRetMsg.setDrType(CS.DrType.OTHER.getType());
|
||||
}else if("D".equals(debit_type)){
|
||||
channelRetMsg.setDrType(CS.DrType.DEBIT.getType());
|
||||
}else if("C".equals(debit_type)){
|
||||
channelRetMsg.setDrType(CS.DrType.CREDIT.getType());
|
||||
}else{
|
||||
channelRetMsg.setDrType(CS.DrType.OTHER.getType());
|
||||
}
|
||||
channelRetMsg.setChannelOrderId(channelOrderNo);
|
||||
if (DgPayKit.STATE_SUCCESS_S.equals(transStat)) {
|
||||
// 交易状态成功
|
||||
channelRetMsg.setPlatformOrderNo(resData.get("out_trans_id").toString());
|
||||
channelRetMsg.setPlatformMchOrderNo(resData.get("party_order_id").toString());
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
res.setPayData(resData.toString());
|
||||
}else if (DgPayKit.STATE_FAIL_F.equals(transStat)) {
|
||||
// 交易状态失败
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}else {
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
// 开启轮询查单
|
||||
channelRetMsg.setNeedQuery(true);
|
||||
}
|
||||
|
||||
} else if (DgPayKit.STATE_ING.equals(code)) {
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
// 开启轮询查单
|
||||
channelRetMsg.setNeedQuery(true);
|
||||
} else{
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}
|
||||
}catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.payway;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelJsapiMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliJsapiOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliJsapiOrderRS;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgPayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgpayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 斗拱 支付宝 jsapi
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/6/13 17:20
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("dgpayPaymentByAliJsapiService") //Service Name需保持全局唯一性
|
||||
public class AliJsapi extends DgpayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
|
||||
AliJsapiOrderRQ bizRQ = (AliJsapiOrderRQ) rq;
|
||||
if(StringUtils.isEmpty(bizRQ.getBuyerUserId())){
|
||||
throw new BizException("[buyerUserId]不可为空");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext){
|
||||
AliJsapiOrderRS res = ApiResBuilder.buildSuccess(AliJsapiOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
try {
|
||||
AliJsapiOrderRQ bizRQ = (AliJsapiOrderRQ) rq;
|
||||
JSONObject dataParams = DgPayKit.dataParams(payOrder, getNotifyUrl());
|
||||
dataParams.put("trade_type", "A_JSAPI");
|
||||
|
||||
JSONObject aliJson = new JSONObject();
|
||||
aliJson.put("buyer_id", bizRQ.getBuyerUserId());
|
||||
dataParams.put("alipay_data", aliJson.toJSONString());
|
||||
|
||||
// 设置订单是否需要分账
|
||||
if(isDivisionOrder(payOrder)) {
|
||||
dataParams.put("delay_acct_flag", "Y");
|
||||
}
|
||||
|
||||
JSONObject response = DgPayKit.payRequest(mchAppConfigContext, dataParams, "/trade/payment/jspay", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
channelRetMsg.setChannelBizData(resData);
|
||||
String code = resData.getString("resp_code");
|
||||
if(DgPayKit.STATE_ING.equals(code)){
|
||||
String channelOrderNo = resData.get("hf_seq_id").toString();
|
||||
//付款信息
|
||||
JSONObject aliResJson = resData.getJSONObject("pay_info");
|
||||
channelRetMsg.setChannelOrderId(channelOrderNo);
|
||||
// 获取payInfo
|
||||
String tradeNo = aliResJson.getString("tradeNO");
|
||||
res.setAlipayTradeNo(tradeNo);
|
||||
res.setPayData(JSON.toJSONString(new ChannelJsapiMsg(tradeNo)));
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
}else { //其他状态, 表示下单失败
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}
|
||||
}catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.payway;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelJsapiMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliJsapiOrderRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliLiteOrderRQ;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgPayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgpayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 支付宝小程序
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2023/1/6 16:53
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("dgpayPaymentByAliLiteService") //Service Name需保持全局唯一性
|
||||
public class AliLite extends DgpayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
|
||||
AliLiteOrderRQ bizRQ = (AliLiteOrderRQ) rq;
|
||||
if (StringUtils.isEmpty(bizRQ.getBuyerUserId())) {
|
||||
throw new BizException("[buyerUserId]不可为空");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
|
||||
AliLiteOrderRQ bizRQ = (AliLiteOrderRQ) rq;
|
||||
// 构造函数响应数据
|
||||
AliJsapiOrderRS res = ApiResBuilder.buildSuccess(AliJsapiOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
try {
|
||||
JSONObject dataParams = DgPayKit.dataParams(payOrder, getNotifyUrl());
|
||||
dataParams.put("trade_type", "A_JSAPI");
|
||||
|
||||
JSONObject aliJson = new JSONObject();
|
||||
aliJson.put("buyer_id", bizRQ.getBuyerUserId());
|
||||
dataParams.put("alipay_data", aliJson.toJSONString());
|
||||
|
||||
// 设置订单是否需要分账
|
||||
if(isDivisionOrder(payOrder)) {
|
||||
dataParams.put("delay_acct_flag", "Y");
|
||||
}
|
||||
JSONObject response = DgPayKit.payRequest(mchAppConfigContext, dataParams, "/trade/payment/jspay", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
channelRetMsg.setChannelBizData(resData);
|
||||
if(DgPayKit.STATE_ING.equals(code)){
|
||||
String channelOrderNo = resData.get("hf_seq_id").toString();
|
||||
//付款信息
|
||||
JSONObject aliResJson = resData.getJSONObject("pay_info");
|
||||
String tradeNo = aliResJson.getString("tradeNO");
|
||||
res.setAlipayTradeNo(tradeNo);
|
||||
res.setPayData(JSON.toJSONString(new ChannelJsapiMsg(tradeNo)));
|
||||
// 支付中
|
||||
channelRetMsg.setChannelOrderId(channelOrderNo);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
// 开启轮询查单
|
||||
channelRetMsg.setNeedQuery(true);
|
||||
}else {
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}
|
||||
|
||||
}catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.payway;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelJsapiMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliQrOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AliQrOrderRS;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgPayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgpayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 斗拱 支付宝扫码
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/5/24 17:38
|
||||
*/
|
||||
@Service("dgpayPaymentByAliQrService") //Service Name需保持全局唯一性
|
||||
public class AliQr extends DgpayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext){
|
||||
|
||||
AliQrOrderRQ aliQrOrderRQ = (AliQrOrderRQ)rq;
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
// 构造函数响应数据
|
||||
AliQrOrderRS res = ApiResBuilder.buildSuccess(AliQrOrderRS.class);
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
JSONObject dataParams = DgPayKit.dataParams(payOrder, getNotifyUrl());
|
||||
dataParams.put("trade_type", "A_NATIVE");
|
||||
// 设置订单是否需要分账
|
||||
if(isDivisionOrder(payOrder)) {
|
||||
dataParams.put("delay_acct_flag", "Y");
|
||||
}
|
||||
|
||||
JSONObject response = DgPayKit.payRequest(mchAppConfigContext, dataParams, "/trade/payment/jspay", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
channelRetMsg.setChannelBizData(resData);
|
||||
if (DgPayKit.STATE_ING.equals(code)) {
|
||||
|
||||
String channelOrderNo = resData.get("hf_seq_id").toString();
|
||||
//付款信息
|
||||
String qrCdLink = resData.getString("qr_code");
|
||||
channelRetMsg.setChannelOrderId(channelOrderNo);
|
||||
ChannelJsapiMsg jsapiMsg = new ChannelJsapiMsg();
|
||||
if(CS.PAY_DATA_TYPE.CODE_IMG_URL.equals(aliQrOrderRQ.getPayDataType())){ //二维码地址
|
||||
res.setCodeImgUrl(sysConfigService.getDBApplicationConfig().genScanImgUrl(qrCdLink));
|
||||
jsapiMsg.setQrCodeUrl(sysConfigService.getDBApplicationConfig().genScanImgUrl(qrCdLink));
|
||||
}else{ //默认都为跳转地址方式
|
||||
jsapiMsg.setQrCodeUrl(qrCdLink);
|
||||
res.setCodeUrl(qrCdLink);
|
||||
}
|
||||
res.setPayData(JSON.toJSONString(jsapiMsg));
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
}else {
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.payway;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AutoPosOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.AutoPosOrderRS;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgPayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgpayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 斗拱 智能POS
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2022/8/2 18:11
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("dgpayPaymentByAutoPosService") //Service Name需保持全局唯一性
|
||||
public class AutoPos extends DgpayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
if(StringUtils.isEmpty(payOrder.getDeviceNo())){
|
||||
throw new BizException("智能POS[deviceNo]不可为空");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
|
||||
String logPrefix = "【斗拱 智能POS支付】";
|
||||
AutoPosOrderRS res = ApiResBuilder.buildSuccess(AutoPosOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
AutoPosOrderRQ bizRQ = (AutoPosOrderRQ) rq;
|
||||
|
||||
try {
|
||||
|
||||
// 请求数据data
|
||||
JSONObject dataParams = new JSONObject();
|
||||
dataParams.put("device_id", payOrder.getDeviceNo());
|
||||
|
||||
// 交易信息
|
||||
JSONObject tradeJSON = new JSONObject();
|
||||
tradeJSON.put("interfaceType", "payment");
|
||||
tradeJSON.put("channelId", DgPayKit.covertChannelId(bizRQ.getChannelType()));
|
||||
tradeJSON.put("mobilePayType", DgPayKit.covertMobilePayType(bizRQ.getPayType()));
|
||||
tradeJSON.put("ordAmt", payOrder.getFindAmt().toString());
|
||||
tradeJSON.put("outOrdId", payOrder.getPayOrderId());
|
||||
tradeJSON.put("goodsDesc", payOrder.getBody());
|
||||
tradeJSON.put("bgRetUrl", "virgo://" + getPosNotifyUrl());
|
||||
tradeJSON.put("ordRemark", payOrder.getSellerRemark());
|
||||
|
||||
// 设置订单是否需要分账
|
||||
if(isDivisionOrder(payOrder)) {
|
||||
tradeJSON.put("isDelayAcct", isDivisionOrder(payOrder) ? "1" : "0");
|
||||
}
|
||||
|
||||
dataParams.put("json_data", tradeJSON.toJSONString());
|
||||
|
||||
JSONObject response = DgPayKit.request(mchAppConfigContext, dataParams, "/trade/cloudmis/device/information", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
channelRetMsg.setChannelBizData(resData);
|
||||
String code = resData.getString("resp_code");
|
||||
if(!DgPayKit.STATE_SUCCESS.equals(code)){
|
||||
log.error("{}推送订单失败,错误码:{},错误信息:{}", logPrefix, code, resData.getString("resp_desc"));
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
channelRetMsg.setChannelErrCode(resData.getString("result_code"));
|
||||
channelRetMsg.setChannelErrMsg(resData.getString("result_msg"));
|
||||
return res;
|
||||
}
|
||||
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING); // 调用成功,改为支付中
|
||||
|
||||
}catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.payway;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.DcepBarOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.DcepBarOrderRS;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgPayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgpayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 斗拱 微信 条码支付
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/6/13 18:03
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("dgpayPaymentByDcepBarService") //Service Name需保持全局唯一性
|
||||
public class DcepBar extends DgpayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
DcepBarOrderRQ bizRQ = (DcepBarOrderRQ) rq;
|
||||
if(StringUtils.isEmpty(bizRQ.getAuthCode())){
|
||||
throw new BizException("用户支付条码[authCode]不可为空");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
|
||||
DcepBarOrderRQ bizRQ = (DcepBarOrderRQ) rq;
|
||||
DcepBarOrderRS res = ApiResBuilder.buildSuccess(DcepBarOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
JSONObject dataParams = DgPayKit.dataParams(payOrder, getNotifyUrl());
|
||||
dataParams.put("auth_code", bizRQ.getAuthCode());
|
||||
// 设置订单是否需要分账
|
||||
if(isDivisionOrder(payOrder)) {
|
||||
dataParams.put("delay_acct_flag", "Y");
|
||||
}
|
||||
|
||||
JSONObject response = DgPayKit.payRequest(mchAppConfigContext, dataParams, "/trade/payment/micropay", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
channelRetMsg.setChannelBizData(resData);
|
||||
String code = resData.getString("resp_code");
|
||||
if(DgPayKit.STATE_SUCCESS.equals(code)){
|
||||
String transStat = resData.getString("trans_stat");
|
||||
String channelOrderNo = resData.get("hf_seq_id").toString();
|
||||
channelRetMsg.setChannelOrderId(channelOrderNo);
|
||||
if (DgPayKit.STATE_SUCCESS_S.equals(transStat)) {
|
||||
// 交易状态成功
|
||||
channelRetMsg.setPlatformOrderNo(resData.get("out_trans_id").toString());
|
||||
channelRetMsg.setPlatformMchOrderNo(resData.get("party_order_id").toString());
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
res.setPayData(resData.toString());
|
||||
String debit_type = resData.getString("debit_type");
|
||||
if(StringUtils.isEmpty(debit_type) || "0".equals(debit_type)){
|
||||
channelRetMsg.setDrType(CS.DrType.OTHER.getType());
|
||||
}else if("D".equals(debit_type)){
|
||||
channelRetMsg.setDrType(CS.DrType.DEBIT.getType());
|
||||
}else if("C".equals(debit_type)){
|
||||
channelRetMsg.setDrType(CS.DrType.CREDIT.getType());
|
||||
}else{
|
||||
channelRetMsg.setDrType(CS.DrType.OTHER.getType());
|
||||
}
|
||||
}else if (DgPayKit.STATE_FAIL_F.equals(transStat)) {
|
||||
// 交易状态失败
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}else {
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
// 开启轮询查单
|
||||
channelRetMsg.setNeedQuery(true);
|
||||
}
|
||||
|
||||
} else if (DgPayKit.STATE_ING.equals(code)){
|
||||
String channelOrderNo = resData.get("hf_seq_id").toString();
|
||||
channelRetMsg.setChannelOrderId(channelOrderNo);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
// 开启轮询查单
|
||||
channelRetMsg.setNeedQuery(true);
|
||||
}else{ //其他状态, 表示下单失败
|
||||
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.payway;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelJsapiMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.DcepQrOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.DcepQrOrderRS;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgPayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgpayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 斗拱 支付宝扫码
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/5/24 17:38
|
||||
*/
|
||||
@Service("dgpayPaymentByDcepQrService") //Service Name需保持全局唯一性
|
||||
public class DcepQr extends DgpayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext){
|
||||
|
||||
DcepQrOrderRQ aliQrOrderRQ = (DcepQrOrderRQ)rq;
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
// 构造函数响应数据
|
||||
DcepQrOrderRS res = ApiResBuilder.buildSuccess(DcepQrOrderRS.class);
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
JSONObject dataParams = DgPayKit.dataParams(payOrder, getNotifyUrl());
|
||||
dataParams.put("trade_type", "D_NATIVE");
|
||||
// 设置订单是否需要分账
|
||||
if(isDivisionOrder(payOrder)) {
|
||||
dataParams.put("delay_acct_flag", "Y");
|
||||
}
|
||||
|
||||
JSONObject response = DgPayKit.payRequest(mchAppConfigContext, dataParams, "/trade/payment/jspay", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
channelRetMsg.setChannelBizData(resData);
|
||||
if (DgPayKit.STATE_ING.equals(code)) {
|
||||
|
||||
String channelOrderNo = resData.get("hf_seq_id").toString();
|
||||
//付款信息
|
||||
String qrCdLink = resData.getString("qr_code");
|
||||
channelRetMsg.setChannelOrderId(channelOrderNo);
|
||||
ChannelJsapiMsg jsapiMsg = new ChannelJsapiMsg();
|
||||
if(CS.PAY_DATA_TYPE.CODE_IMG_URL.equals(aliQrOrderRQ.getPayDataType())){ //二维码地址
|
||||
jsapiMsg.setQrCodeUrl(sysConfigService.getDBApplicationConfig().genScanImgUrl(qrCdLink));
|
||||
res.setCodeImgUrl(sysConfigService.getDBApplicationConfig().genScanImgUrl(qrCdLink));
|
||||
}else{ //默认都为跳转地址方式
|
||||
jsapiMsg.setQrCodeUrl(qrCdLink);
|
||||
res.setCodeUrl(qrCdLink);
|
||||
}
|
||||
res.setPayData(JSON.toJSONString(jsapiMsg));
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
}else {
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.payway;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelJsapiMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.UpQrOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.UpQrOrderRS;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgPayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgpayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 银联扫码支付
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2022/06/22 20:09
|
||||
*/
|
||||
@Service("dgpayPaymentByUpQrService") //Service Name需保持全局唯一性
|
||||
@Slf4j
|
||||
public class UpQr extends DgpayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext){
|
||||
|
||||
UpQrOrderRQ bizRQ = (UpQrOrderRQ)rq;
|
||||
// 构造函数响应数据
|
||||
UpQrOrderRS res = ApiResBuilder.buildSuccess(UpQrOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
try {
|
||||
JSONObject dataParams = DgPayKit.dataParams(payOrder, getNotifyUrl());
|
||||
dataParams.put("trade_type", "U_NATIVE");
|
||||
|
||||
// 设置订单是否需要分账
|
||||
if(isDivisionOrder(payOrder)) {
|
||||
dataParams.put("delay_acct_flag", "Y");
|
||||
}
|
||||
|
||||
JSONObject response = DgPayKit.payRequest(mchAppConfigContext, dataParams, "/trade/payment/jspay", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
channelRetMsg.setChannelBizData(resData);
|
||||
if (DgPayKit.STATE_ING.equals(code)) {
|
||||
|
||||
String channelOrderNo = resData.get("hf_seq_id").toString();
|
||||
//付款信息
|
||||
String qrCdLink = resData.getString("qr_code");
|
||||
channelRetMsg.setChannelOrderId(channelOrderNo);
|
||||
ChannelJsapiMsg jsapiMsg = new ChannelJsapiMsg();
|
||||
if(CS.PAY_DATA_TYPE.CODE_IMG_URL.equals(bizRQ.getPayDataType())){ //二维码地址
|
||||
res.setCodeImgUrl(sysConfigService.getDBApplicationConfig().genScanImgUrl(qrCdLink));
|
||||
jsapiMsg.setQrCodeUrl(sysConfigService.getDBApplicationConfig().genScanImgUrl(qrCdLink));
|
||||
}else{ //默认都为跳转地址方式
|
||||
res.setCodeUrl(qrCdLink);
|
||||
jsapiMsg.setQrCodeUrl(qrCdLink);
|
||||
}
|
||||
res.setPayData(JSON.toJSONString(jsapiMsg));
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
}else {
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}
|
||||
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
return res;
|
||||
|
||||
}catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.payway;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.WxBarOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.WxBarOrderRS;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgPayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgpayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 斗拱 微信 条码支付
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/6/13 18:03
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("dgPaymentByWxBarService") //Service Name需保持全局唯一性
|
||||
public class WxBar extends DgpayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
WxBarOrderRQ bizRQ = (WxBarOrderRQ) rq;
|
||||
if(StringUtils.isEmpty(bizRQ.getAuthCode())){
|
||||
throw new BizException("用户支付条码[authCode]不可为空");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
|
||||
WxBarOrderRQ bizRQ = (WxBarOrderRQ) rq;
|
||||
WxBarOrderRS res = ApiResBuilder.buildSuccess(WxBarOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
JSONObject dataParams = DgPayKit.dataParams(payOrder, getNotifyUrl());
|
||||
dataParams.put("auth_code", bizRQ.getAuthCode());
|
||||
// 设置订单是否需要分账
|
||||
if(isDivisionOrder(payOrder)) {
|
||||
dataParams.put("delay_acct_flag", "Y");
|
||||
}
|
||||
|
||||
JSONObject response = DgPayKit.payRequest(mchAppConfigContext, dataParams, "/trade/payment/micropay", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
channelRetMsg.setChannelBizData(resData);
|
||||
if(DgPayKit.STATE_SUCCESS.equals(code)){
|
||||
String transStat = resData.getString("trans_stat");
|
||||
String channelOrderNo = resData.get("hf_seq_id").toString();
|
||||
channelRetMsg.setChannelOrderId(channelOrderNo);
|
||||
if (DgPayKit.STATE_SUCCESS_S.equals(transStat)) {
|
||||
// 交易状态成功
|
||||
channelRetMsg.setPlatformOrderNo(resData.get("out_trans_id").toString());
|
||||
channelRetMsg.setPlatformMchOrderNo(resData.get("party_order_id").toString());
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
res.setPayData(resData.toString());
|
||||
String debit_type = resData.getString("debit_type");
|
||||
if(StringUtils.isEmpty(debit_type) || "0".equals(debit_type)){
|
||||
channelRetMsg.setDrType(CS.DrType.OTHER.getType());
|
||||
}else if("D".equals(debit_type)){
|
||||
channelRetMsg.setDrType(CS.DrType.DEBIT.getType());
|
||||
}else if("C".equals(debit_type)){
|
||||
channelRetMsg.setDrType(CS.DrType.CREDIT.getType());
|
||||
}else{
|
||||
channelRetMsg.setDrType(CS.DrType.OTHER.getType());
|
||||
}
|
||||
}else if (DgPayKit.STATE_FAIL_F.equals(transStat)) {
|
||||
// 交易状态失败
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}else {
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
// 开启轮询查单
|
||||
channelRetMsg.setNeedQuery(true);
|
||||
}
|
||||
|
||||
} else if (DgPayKit.STATE_ING.equals(code)){
|
||||
String channelOrderNo = resData.get("hf_seq_id").toString();
|
||||
channelRetMsg.setChannelOrderId(channelOrderNo);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
// 开启轮询查单
|
||||
channelRetMsg.setNeedQuery(true);
|
||||
}else{ //其他状态, 表示下单失败
|
||||
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.payway;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.oauth2.WxpayOauth2Params;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.WxJsapiOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.WxJsapiOrderRS;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgPayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgpayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 斗拱 微信jsapi
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/6/13 17:40
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("dgpayPaymentByWxJsapiService") //Service Name需保持全局唯一性
|
||||
public class WxJsapi extends DgpayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
|
||||
WxJsapiOrderRQ bizRQ = (WxJsapiOrderRQ) rq;
|
||||
if(StringUtils.isEmpty(bizRQ.getOpenid())){
|
||||
throw new BizException("[openId]不可为空");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
WxJsapiOrderRS res = ApiResBuilder.buildSuccess(WxJsapiOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
try {
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
WxpayOauth2Params oauth2Params = (WxpayOauth2Params)configContextQueryService.queryIsvOauth2Params(mchAppConfigContext.getMchApplyment().getIsvNo(), CS.IF_CODE.WXPAY);
|
||||
|
||||
// 设置请求参数
|
||||
WxJsapiOrderRQ bizRQ = (WxJsapiOrderRQ) rq;
|
||||
JSONObject dataParams = DgPayKit.dataParams(payOrder, getNotifyUrl());
|
||||
dataParams.put("trade_type", "T_JSAPI");
|
||||
JSONObject wxJson = new JSONObject();
|
||||
// wxJson.put("sub_appid", oauth2Params.getAppId());
|
||||
wxJson.put("openid", bizRQ.getChannelUserId());
|
||||
// 接口上传的appId
|
||||
if (StringUtils.isNotEmpty(bizRQ.getSubAppid())) {
|
||||
wxJson.put("sub_appid", bizRQ.getSubAppid());
|
||||
}else{
|
||||
wxJson.put("sub_appid", oauth2Params.getAppId());
|
||||
}
|
||||
dataParams.put("wx_data", wxJson.toJSONString());
|
||||
// 设置订单是否需要分账
|
||||
if(isDivisionOrder(payOrder)) {
|
||||
dataParams.put("delay_acct_flag", "Y");
|
||||
}
|
||||
|
||||
JSONObject response = DgPayKit.payRequest(mchAppConfigContext, dataParams, "/trade/payment/jspay", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
String code = resData.getString("resp_code");
|
||||
channelRetMsg.setChannelBizData(resData);
|
||||
if(DgPayKit.STATE_ING.equals(code)){
|
||||
String channelOrderNo = resData.get("hf_seq_id").toString();
|
||||
//付款信息
|
||||
String payInfo = resData.getString("pay_info");
|
||||
channelRetMsg.setChannelOrderId(channelOrderNo);
|
||||
// 获取payInfo
|
||||
res.setPayInfo(payInfo);
|
||||
res.setPayData(payInfo);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
}else { //其他状态, 表示下单失败
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}
|
||||
}catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.payway;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.oauth2.WxpayOauth2Params;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.WxLiteOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.WxLiteOrderRS;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgPayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgpayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 斗拱 微信jsapi
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/6/13 17:52
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("dgpayPaymentByWxLiteService") //Service Name需保持全局唯一性
|
||||
public class WxLite extends DgpayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
|
||||
WxLiteOrderRQ bizRQ = (WxLiteOrderRQ) rq;
|
||||
if(StringUtils.isEmpty(bizRQ.getOpenid())){
|
||||
throw new BizException("[openId]不可为空");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
WxLiteOrderRS res = ApiResBuilder.buildSuccess(WxLiteOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
try {
|
||||
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
WxpayOauth2Params oauth2Params = (WxpayOauth2Params) configContextQueryService.queryIsvOauth2Params(mchAppConfigContext.getMchApplyment().getIsvNo(), CS.IF_CODE.WXPAY);
|
||||
|
||||
// 设置请求参数
|
||||
WxLiteOrderRQ bizRQ = (WxLiteOrderRQ) rq;
|
||||
JSONObject dataParams = DgPayKit.dataParams(payOrder, getNotifyUrl());
|
||||
dataParams.put("trade_type", "T_MINIAPP");
|
||||
|
||||
JSONObject wxJson = new JSONObject();
|
||||
wxJson.put("sub_appid", oauth2Params.getLiteAppId());
|
||||
wxJson.put("sub_openid", bizRQ.getChannelUserId());
|
||||
|
||||
// 接口上传的appId
|
||||
if (StringUtils.isNotEmpty(bizRQ.getSubAppid())) {
|
||||
wxJson.put("sub_appid", bizRQ.getSubAppid());
|
||||
}
|
||||
dataParams.put("wx_data", wxJson.toJSONString());
|
||||
|
||||
// 设置订单是否需要分账
|
||||
if(isDivisionOrder(payOrder)) {
|
||||
dataParams.put("delay_acct_flag", "Y");
|
||||
}
|
||||
|
||||
JSONObject response = DgPayKit.payRequest(mchAppConfigContext, dataParams, "/trade/payment/jspay", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
channelRetMsg.setChannelBizData(resData);
|
||||
String code = resData.getString("resp_code");
|
||||
if(DgPayKit.STATE_ING.equals(code)){
|
||||
String channelOrderNo = resData.get("hf_seq_id").toString();
|
||||
//付款信息
|
||||
String payInfo = resData.getString("pay_info");
|
||||
channelRetMsg.setChannelOrderId(channelOrderNo);
|
||||
// 获取payInfo
|
||||
res.setPayInfo(payInfo);
|
||||
res.setPayData(payInfo);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
// 开启轮询查单
|
||||
channelRetMsg.setNeedQuery(true);
|
||||
}else { //其他状态, 表示下单失败
|
||||
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}
|
||||
}catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.payway;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelJsapiMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.YsfJsapiOrderRQ;
|
||||
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.YsfJsapiOrderRS;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgPayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.dgpay.DgpayPaymentService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/*
|
||||
* 银联 jsapi
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2021/6/8 18:11
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("dgpayPaymentByYsfJsapiService") //Service Name需保持全局唯一性
|
||||
public class YsfJsapi extends DgpayPaymentService {
|
||||
|
||||
@Override
|
||||
public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {
|
||||
|
||||
YsfJsapiOrderRQ bizRQ = (YsfJsapiOrderRQ) rq;
|
||||
if(StringUtils.isEmpty(bizRQ.getUserId())){
|
||||
throw new BizException("[userId]不可为空");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
|
||||
YsfJsapiOrderRS res = ApiResBuilder.buildSuccess(YsfJsapiOrderRS.class);
|
||||
ChannelRetMsg channelRetMsg = new ChannelRetMsg();
|
||||
res.setChannelRetMsg(channelRetMsg);
|
||||
|
||||
try {
|
||||
YsfJsapiOrderRQ bizRQ = (YsfJsapiOrderRQ) rq;
|
||||
JSONObject dataParams = DgPayKit.dataParams(payOrder, getNotifyUrl());
|
||||
dataParams.put("trade_type", "U_JSAPI");
|
||||
|
||||
JSONObject jsapiJson = new JSONObject();
|
||||
jsapiJson.put("customer_ip", payOrder.getClientIp());
|
||||
jsapiJson.put("user_id", bizRQ.getUserId());
|
||||
dataParams.put("unionpay_data", jsapiJson.toJSONString());
|
||||
|
||||
// 设置订单是否需要分账
|
||||
if(isDivisionOrder(payOrder)) {
|
||||
dataParams.put("delay_acct_flag", "Y");
|
||||
}
|
||||
|
||||
JSONObject response = DgPayKit.payRequest(mchAppConfigContext, dataParams, "/trade/payment/jspay", payOrder.getIfCode());
|
||||
JSONObject resData = response.getJSONObject("data");
|
||||
channelRetMsg.setChannelBizData(resData);
|
||||
String code = resData.getString("resp_code");
|
||||
if (DgPayKit.STATE_ING.equals(code)) {
|
||||
String channelOrderNo = resData.getString("hf_seq_id");
|
||||
//付款信息
|
||||
String payInfo = resData.getString("pay_info");
|
||||
channelRetMsg.setChannelOrderId(channelOrderNo);
|
||||
res.setRedirectUrl(payInfo);
|
||||
ChannelJsapiMsg channelJsapiMsg = new ChannelJsapiMsg();
|
||||
channelJsapiMsg.setRedirectUrl(payInfo);
|
||||
res.setPayData(JSON.toJSONString(channelJsapiMsg));
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
}else {
|
||||
DgPayKit.channelMsgError(resData, channelRetMsg);
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
}
|
||||
return res;
|
||||
|
||||
}catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
channelRetMsg.setChannelErrMsg("系统异常");
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class DgUtils {
|
||||
|
||||
private static List<Map<String, String>> limitList = new ArrayList<>();
|
||||
|
||||
static {
|
||||
Map<String, String> item = new HashMap<>();
|
||||
item.put("name", "贵州省");
|
||||
item.put("code", "520000");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "湖南省");
|
||||
item.put("code", "430000");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "陕西省");
|
||||
item.put("code", "610000");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "河南省");
|
||||
item.put("code", "410000");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "浙江省");
|
||||
item.put("code", "330000");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "重庆市");
|
||||
item.put("code", "500100");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "云南省");
|
||||
item.put("code", "530000");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "湖北省");
|
||||
item.put("code", "420000");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "福建省");
|
||||
item.put("code", "350000");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "宁夏回族自治区");
|
||||
item.put("code", "640000");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "吉林省");
|
||||
item.put("code", "220000");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "黑龙江省");
|
||||
item.put("code", "230000");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "江苏省");
|
||||
item.put("code", "320000");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "海南省");
|
||||
item.put("code", "460000");
|
||||
limitList.add(item);
|
||||
|
||||
item = new HashMap<>();
|
||||
item.put("name", "青海省");
|
||||
item.put("code", "630000");
|
||||
limitList.add(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检验银联限制
|
||||
* @param provinceCode
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkBankLimitArea(String provinceCode) {
|
||||
for (Map<String, String> item : limitList) {
|
||||
if (provinceCode.equals(item.get("code"))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.dgpay.utils;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @ClassName MD5Utils
|
||||
* @Description
|
||||
* @Author boy
|
||||
* @Date 2019/8/30 8:29 PM
|
||||
*/
|
||||
public class MD5Utils {
|
||||
static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
static String MD5 = "MD5";//加签方式:MD5
|
||||
|
||||
/*
|
||||
* @Author boy
|
||||
* @Description 数据签名
|
||||
* @Date 2019/8/31 1:57 PM
|
||||
* @Param [data, key]
|
||||
* @return java.lang.String
|
||||
*/
|
||||
public static String sign(String data, String key) throws Exception {
|
||||
//得到明文的字节数组
|
||||
byte[] btInput = (data + key).getBytes();
|
||||
// 创建一个提供信息摘要算法的对象(MD5摘要算法)
|
||||
MessageDigest messageDigest = MessageDigest.getInstance(MD5);
|
||||
// 使用指定的字节更新摘要
|
||||
messageDigest.update(btInput);
|
||||
// 得到二进制的密文
|
||||
byte[] encryptData = messageDigest.digest();
|
||||
// 把密文转换成十六进制的字符串形式
|
||||
String encryptDataStr = bytesToHex(encryptData);
|
||||
return encryptDataStr;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @Author boy
|
||||
* @Description 验签
|
||||
* @Date 2019/8/31 1:57 PM
|
||||
* @Param [data, key, sign][明文数据,签名key,接收到的签名]
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean verifySign(String data, String key, String sign) throws Exception {
|
||||
//调用加签方法,看加签后的签名是否和接收到的一致
|
||||
String encryptData = sign(data, key);
|
||||
if (encryptData.equals(sign)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @Author boy
|
||||
* @Description 将byte数组转化为16进制字符串
|
||||
* @Date 2019/8/31 1:58 PM
|
||||
* @Param [bytes]
|
||||
* @return java.lang.String
|
||||
*/
|
||||
public static String bytesToHex(byte[] bytes) {
|
||||
int k = 0;
|
||||
char[] hexChars = new char[bytes.length * 2];
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
byte byte0 = bytes[i];
|
||||
hexChars[k++] = hexDigits[byte0 >>> 4 & 0xf];
|
||||
hexChars[k++] = hexDigits[byte0 & 0xf];
|
||||
}
|
||||
return new String(hexChars);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Map<String, String> hashMap = new HashMap<>();
|
||||
String data = "你好!MD你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!你好!MD5!5!";
|
||||
String key = "1234567890abcdef";//密钥
|
||||
String dataSign = MD5Utils.sign(data, key);
|
||||
hashMap.put("data", data);
|
||||
hashMap.put("dataSign", dataSign);
|
||||
System.out.println("明文:" + hashMap.get("data"));
|
||||
System.out.println("签名:" + hashMap.get("dataSign"));
|
||||
System.out.println("验签结果:" + MD5Utils.verifySign(data, key, dataSign));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.flpay;
|
||||
|
||||
import cn.hutool.crypto.digest.DigestUtil;
|
||||
import cn.hutool.crypto.digest.HmacAlgorithm;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.DBPaymentConfig;
|
||||
import com.jeequan.jeepay.core.utils.JeepayKit;
|
||||
import com.jeequan.jeepay.thirdparty.channel.flpay.model.ReqEntity;
|
||||
import com.jeequan.jeepay.thirdparty.channel.flpay.model.ReqMethod;
|
||||
import com.jeequan.jeepay.thirdparty.channel.flpay.model.RespEntity;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* 福禄打款
|
||||
* @author crystal
|
||||
* @date 2024/3/25 11:09
|
||||
*/
|
||||
@Slf4j
|
||||
public class FlKit {
|
||||
|
||||
/**
|
||||
* 发起请求
|
||||
* @param method
|
||||
* @param config
|
||||
* @param bizData
|
||||
* @return
|
||||
*/
|
||||
public static JSONObject reqApi(ReqMethod.Method method, DBPaymentConfig config, JSONObject bizData) {
|
||||
ReqEntity reqEntity = initSign(config,bizData);
|
||||
String url = ReqMethod.getUrl(config,method);
|
||||
log.info("【福禄】请求参数:{}",JSON.toJSONString(reqEntity));
|
||||
HttpResponse response = HttpRequest.post(url).body(JSON.toJSONString(reqEntity)).execute();
|
||||
if(!response.isOk()){
|
||||
throw ChannelException.sysError("付款接口请求异常");
|
||||
}
|
||||
log.info("【福禄】返回参数:{}",response.body());
|
||||
RespEntity respEntity = JSON.parseObject(response.body(), RespEntity.class);
|
||||
return initResult(respEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 公共返回参数处理
|
||||
* @param resp
|
||||
* @return
|
||||
*/
|
||||
public static JSONObject initResult(RespEntity resp) {
|
||||
if(!resp.isSuccess()){
|
||||
String msg = StringUtils.isNotEmpty(resp.getMsg()) ? resp.getMsg() : resp.getSubMsg();
|
||||
throw ChannelException.sysError(msg);
|
||||
}
|
||||
return JSON.parseObject(resp.getData());
|
||||
}
|
||||
|
||||
public static ReqEntity initSign(DBPaymentConfig config,JSONObject bizData){
|
||||
bizData.put("taskNo", config.getTaskNo());
|
||||
bizData.put("appId", config.getAppId());
|
||||
ReqEntity reqEntity = new ReqEntity(config.getAppId(),bizData);
|
||||
reqEntity.setSign(genSign(reqEntity,config));
|
||||
return reqEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验回调签名
|
||||
* @param reqEntity
|
||||
* @param config
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkResultNotify(ReqEntity reqEntity, DBPaymentConfig config) {
|
||||
String sign = genSign(reqEntity,config);
|
||||
return !sign.equalsIgnoreCase(reqEntity.getSign());
|
||||
}
|
||||
|
||||
private static String genSign(ReqEntity reqEntity,DBPaymentConfig config) {
|
||||
String signStr = JeepayKit.getStrSort(reqEntity.toMap());
|
||||
//前5位
|
||||
String prefix = config.getSecret().substring(0,5);
|
||||
//后5位
|
||||
String suffix = config.getSecret().substring(config.getSecret().length() - 5);
|
||||
//拼接在首尾
|
||||
String signContent = prefix + signStr + suffix;
|
||||
try {
|
||||
String signText = DigestUtil.sha256Hex(signContent);
|
||||
byte[] secretSigning = DigestUtil.hmac(HmacAlgorithm.HmacSHA256, config.getSecret().getBytes(StandardCharsets.UTF_8)).digest(reqEntity.getTimestamp());
|
||||
String sign = DatatypeConverter.printHexBinary(DigestUtil.hmac(HmacAlgorithm.HmacSHA256,secretSigning).digest(signText)).toLowerCase();
|
||||
return sign;
|
||||
} catch (Exception e) {
|
||||
throw new BizException("生成签名异常");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.flpay;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.CashoutRecord;
|
||||
import com.jeequan.jeepay.core.exception.ChannelException;
|
||||
import com.jeequan.jeepay.core.model.DBPaymentConfig;
|
||||
import com.jeequan.jeepay.core.model.df.Account;
|
||||
import com.jeequan.jeepay.core.model.df.PaymentSign;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.utils.AmountUtil;
|
||||
import com.jeequan.jeepay.db.entity.AccountFundInfo;
|
||||
import com.jeequan.jeepay.db.entity.AccountInfo;
|
||||
import com.jeequan.jeepay.service.impl.AccountInfoService;
|
||||
import com.jeequan.jeepay.thirdparty.channel.flpay.model.ReqMethod;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractRepayApiService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* 福禄打款
|
||||
* @author crystal
|
||||
* @date 2024/3/25 10:38
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class FlpayRepayApiService extends AbstractRepayApiService {
|
||||
|
||||
@Autowired
|
||||
private AccountInfoService accountInfoService;
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.FLPAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否需要签约
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isSign() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preCheck(String mchNo,byte accountType,Long changeAmt) {
|
||||
this.checkAccountBalance(mchNo,accountType,changeAmt);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询账户余额
|
||||
* @param mchNo 用户号
|
||||
* @param accountType 账户类型
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Account queryAccountBalance(String mchNo, byte accountType) {
|
||||
AccountInfo accountInfo = accountInfoService.getAccountInfo(mchNo, accountType);
|
||||
return new Account(accountInfo.getBalacne(),accountInfo.getFreeze());
|
||||
}
|
||||
|
||||
/**
|
||||
* 签约正常 签约状态(0-待处理 1-校验失败 2-待签约 3-签约成功 4-校验错误)
|
||||
* @param sign
|
||||
* @param config
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChannelRetMsg sign(PaymentSign sign, DBPaymentConfig config) {
|
||||
JSONObject bizData = new JSONObject();
|
||||
bizData.put("userName",sign.getUserName());
|
||||
bizData.put("idCard",sign.getIdCard().toUpperCase(Locale.ROOT));
|
||||
bizData.put("mobile",sign.getMobile());
|
||||
JSONObject respBizData = FlKit.reqApi(ReqMethod.Method.SIGN, config, bizData);
|
||||
Integer signStatus = respBizData.getInteger("signStatus");
|
||||
switch (signStatus){
|
||||
case 3:
|
||||
return ChannelRetMsg.confirmSuccess(respBizData.getString("peopleId"));
|
||||
}
|
||||
return ChannelRetMsg.confirmFail(null,respBizData.getString("failReason"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 签约结果查询
|
||||
* @param sign
|
||||
* @param config
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChannelRetMsg querySign(PaymentSign sign, DBPaymentConfig config) {
|
||||
JSONObject bizData = new JSONObject();
|
||||
bizData.put("userName",sign.getUserName());
|
||||
bizData.put("idCard",sign.getIdCard().toUpperCase(Locale.ROOT));
|
||||
JSONObject respBizData = FlKit.reqApi(ReqMethod.Method.SIGN_QUERY, config, bizData);
|
||||
Integer signStatus = respBizData.getInteger("signStatus");
|
||||
switch (signStatus){
|
||||
case 3:
|
||||
return ChannelRetMsg.confirmSuccess(respBizData.getString("peopleId"));
|
||||
}
|
||||
return ChannelRetMsg.confirmFail(null,respBizData.getString("failReason"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 付款
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChannelRetMsg payment(CashoutRecord record,DBPaymentConfig config) {
|
||||
JSONObject bizData = new JSONObject();
|
||||
bizData.put("accountNumber",record.getSettAccountNo());
|
||||
bizData.put("afterTaxAmount", AmountUtil.convertCent2Dollar(AmountUtil.abs(record.getSettAmount())));
|
||||
String grantType = AccountFundInfo.WECHAT.equals(record.getSettAccountType()) ? "微信支付" : AccountFundInfo.ALIPAY == record.getSettAccountType() ? "支付宝" : "银行卡";
|
||||
bizData.put("grantType", grantType);
|
||||
bizData.put("idCard",record.getIdCard());
|
||||
bizData.put("outBizNo",record.getTransferOrderId());
|
||||
bizData.put("mobile",record.getBankPhone());
|
||||
bizData.put("transRemark","账户结算处理");
|
||||
bizData.put("remark",record.getAuditRemark());
|
||||
bizData.put("userName",record.getSettAccountName());
|
||||
bizData.put("notifyUrl",getNotifyUrl());
|
||||
try {
|
||||
JSONObject respBizData = FlKit.reqApi(ReqMethod.Method.PAYMENT, config, bizData);
|
||||
ChannelRetMsg channelRetMsg = ChannelRetMsg.waiting();
|
||||
channelRetMsg.setChannelOrderId(respBizData.getString("bizNo"));
|
||||
channelRetMsg.setChannelBizData(respBizData);
|
||||
return channelRetMsg;
|
||||
}catch (ChannelException e){
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}catch (Exception e){
|
||||
return ChannelRetMsg.confirmFail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 付款结果查询
|
||||
* @param outBizNo 外部请求流水号
|
||||
* @param config
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChannelRetMsg queryPayment(String outBizNo, DBPaymentConfig config) {
|
||||
JSONObject bizData = new JSONObject();
|
||||
bizData.put("outBizNo",outBizNo);
|
||||
try {
|
||||
JSONObject respBizData = FlKit.reqApi(ReqMethod.Method.PAYMENT_QUERY, config, bizData);
|
||||
String failCause = respBizData.getString("failCause");
|
||||
Integer auditStatus = respBizData.getInteger("auditStatus");
|
||||
Integer payStatus = respBizData.getInteger("payStatus");
|
||||
String payFailCause = respBizData.getString("payFailCause");
|
||||
ChannelRetMsg retMsg = ChannelRetMsg.waiting();
|
||||
retMsg.setChannelErrMsg(failCause);
|
||||
switch (auditStatus){
|
||||
case 2:
|
||||
return retMsg;
|
||||
}
|
||||
retMsg.setChannelErrMsg(payFailCause);
|
||||
switch (payStatus){
|
||||
case 3:
|
||||
return ChannelRetMsg.confirmSuccess(respBizData.getString("bizNo"));
|
||||
}
|
||||
return retMsg;
|
||||
}catch (ChannelException e){
|
||||
throw ChannelException.sysError(e.getMessage());
|
||||
}catch (Exception e){
|
||||
return ChannelRetMsg.confirmFail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.flpay;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.exception.ResponseException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IRepayNoticeService;
|
||||
import com.jeequan.jeepay.core.model.DBPaymentConfig;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.db.entity.AccountChangeInfo;
|
||||
import com.jeequan.jeepay.service.impl.AccountChangeInfoService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractRepayNoticeService;
|
||||
import com.jeequan.jeepay.thirdparty.channel.flpay.model.ReqEntity;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.KqpayKit;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @author crystal
|
||||
* @date 2024/3/27 10:43
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class FlpayRepayNoticeService extends AbstractRepayNoticeService {
|
||||
|
||||
@Autowired private SysConfigService sysConfigService;
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.FLPAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数解析
|
||||
* @param request
|
||||
* @param urlOrderId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlOrderId) {
|
||||
JSONObject reqParamJSON = getReqParamJSON();
|
||||
JSONObject bizContent = reqParamJSON.getJSONObject("bizContent");
|
||||
return MutablePair.of(bizContent.getString("bizOutNo"), reqParamJSON);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param request
|
||||
* @param urlOrderId
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChannelRetMsg doNotice(HttpServletRequest request, String urlOrderId, Object params) {
|
||||
JSONObject respJson = (JSONObject) JSON.toJSON(params);
|
||||
boolean verifyResult = verifyParams(respJson);
|
||||
if(!verifyResult){
|
||||
throw ResponseException.buildText("sign check error");
|
||||
}
|
||||
JSONObject biz = respJson.getJSONObject("bizContent");
|
||||
String channelRemark = "【渠道备注】";
|
||||
log.info("【灵工】打款状态回调,打款流水号:{},业务参数:{}", urlOrderId, biz);
|
||||
//失败原因
|
||||
String failCause = biz.getString("failCause");
|
||||
//审核状态 审核状态 0-待审核 1-审核通过 2-人工审核拒绝
|
||||
int auditStatus = biz.getIntValue("auditStatus");
|
||||
//发放状态 发放(推送)状态 0-待发放 1-发放通过 2-发放拒绝
|
||||
int grantStatus = biz.getIntValue("grantStatus");
|
||||
//支付状态 0-未处理 1-待打款 2-打款中 3-打款成功 4-打款失败 5-退票退款
|
||||
int payStatus = biz.getIntValue("payStatus");
|
||||
//支付失败原因
|
||||
String payFailCause = biz.getString("payFailCause");
|
||||
String bizNo = biz.getString("bizNo");
|
||||
ChannelRetMsg retMsg = ChannelRetMsg.waiting();
|
||||
ResponseEntity okResponse = textResp("success");
|
||||
retMsg.setResponseEntity(okResponse);
|
||||
retMsg.setChannelOrderId(bizNo);
|
||||
retMsg.setChannelErrMsg(channelRemark + failCause);
|
||||
if(grantStatus == 2 || auditStatus == 2){
|
||||
return retMsg;
|
||||
}
|
||||
retMsg.setChannelErrMsg(channelRemark + payFailCause);
|
||||
switch (payStatus){
|
||||
case 3:
|
||||
return ChannelRetMsg.confirmSuccess(bizNo);
|
||||
}
|
||||
return retMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验参数
|
||||
* @param noticeData
|
||||
* @return
|
||||
*/
|
||||
public boolean verifyParams(JSONObject noticeData) {
|
||||
DBPaymentConfig config = sysConfigService.getDbPaymentConfig();
|
||||
if(CS.IF_CODE.FLPAY.equals(config.getPaymentType())){
|
||||
try {
|
||||
return FlKit.checkResultNotify(noticeData.toJavaObject(ReqEntity.class),config);
|
||||
}catch (Exception e) {
|
||||
log.error("验证签名异常", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.flpay.model;
|
||||
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* 福禄公共参数请求封装
|
||||
* @author crystal
|
||||
* @date 2024/2/29 11:53
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class ReqEntity {
|
||||
|
||||
|
||||
/**
|
||||
*appid
|
||||
*/
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* 时间戳
|
||||
*/
|
||||
private String timestamp;
|
||||
|
||||
/**
|
||||
* 随机字符串
|
||||
*/
|
||||
private String nonce;
|
||||
|
||||
/**
|
||||
* 请求唯一表示,代表订单号 长度不能超过12
|
||||
*/
|
||||
private String sign;
|
||||
|
||||
/**
|
||||
* 请求回调地址
|
||||
*/
|
||||
private String bizContent;
|
||||
|
||||
|
||||
public ReqEntity(String appId, JSONObject bizData) {
|
||||
this.appId = appId;
|
||||
this.nonce = RandomUtil.randomString(20);
|
||||
if(bizData != null){
|
||||
this.bizContent = bizData.toJSONString();
|
||||
}else{
|
||||
this.bizContent = "{}";
|
||||
}
|
||||
String timestamp = System.currentTimeMillis() + "";
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> params = new HashMap<>(5);
|
||||
params.put("appId",this.appId);
|
||||
params.put("timestamp",this.timestamp);
|
||||
params.put("nonce",this.nonce);
|
||||
params.put("bizContent",this.bizContent);
|
||||
return params;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.flpay.model;
|
||||
|
||||
import com.jeequan.jeepay.core.model.DBPaymentConfig;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @author crystal
|
||||
* @date 2024/3/25 11:40
|
||||
*/
|
||||
@Data
|
||||
public class ReqMethod {
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum Method{
|
||||
|
||||
SIGN("/api/open/uploadPeople","自由职业者签约"),
|
||||
|
||||
SIGN_QUERY("/api/open/queryPeople","自由职业者签约状态查询"),
|
||||
|
||||
PAYMENT("/api/open/uploadPlan","付款接口"),
|
||||
|
||||
ACCOUNT_QUERY("/api/open/queryPayMethod","账户类型查询接口"),
|
||||
|
||||
AUDIT("/api/open/grantPlan","审核下发结算"),
|
||||
|
||||
PAYMENT_QUERY("/api/open/queryPlan","结算发放结果查询接口"),
|
||||
|
||||
;
|
||||
private final String method;
|
||||
|
||||
private final String desc;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** 获取请求接口地址
|
||||
* @param method
|
||||
* @return
|
||||
*/
|
||||
public static String getUrl(DBPaymentConfig config,Method method){
|
||||
return config.getDomain() + method.getMethod();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.flpay.model;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* 福禄通用返回参数封装
|
||||
* @author crystal
|
||||
* @date 2024/3/25 13:51
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class RespEntity {
|
||||
|
||||
public static final int SUCCESS_CODE = 0;
|
||||
|
||||
public static final int SUCCESS_EXT_CODE = 1;
|
||||
|
||||
public static final int NETWORK_ERROR_CODE = 500;
|
||||
|
||||
private int code;
|
||||
|
||||
private String data;
|
||||
|
||||
private String msg;
|
||||
|
||||
private String subCode;
|
||||
|
||||
private String subMsg;
|
||||
|
||||
public RespEntity(int code, String msg) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public static RespEntity fail(String msg) {
|
||||
RespEntity result = new RespEntity(NETWORK_ERROR_CODE,msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否返回成功
|
||||
*/
|
||||
public boolean isSuccess(){
|
||||
return SUCCESS_CODE == this.code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.kqpay;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IGetApplymentDataService;
|
||||
import com.jeequan.jeepay.db.entity.BankBranch;
|
||||
import com.jeequan.jeepay.service.impl.BankBranchService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service("dgpayGetApplymentDataService")
|
||||
@Slf4j
|
||||
public class DgpayGetApplymentDataService implements IGetApplymentDataService {
|
||||
|
||||
@Autowired
|
||||
private BankBranchService bankBranchService;
|
||||
|
||||
@Override
|
||||
public List<JSONObject> getBankBranchInfo(String isvNo, String bankAliasCode, String cityCode, String bankName, String branchName) throws BizException {
|
||||
// Assert.notBlank(bankName, "银行名称不能为空");
|
||||
Page<BankBranch> page = new Page<>();
|
||||
bankBranchService.pageByArea(page, cityCode, bankName, branchName);
|
||||
|
||||
return page.getRecords().stream().map( t -> ((JSONObject) JSON.toJSON(t))).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.kqpay;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.exception.ResponseException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractChannelNoticeService;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.model.KqpayOrderStatus;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 快钱支付 回调接口实现类
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/4/15 10:23
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class KqpayChannelNoticeService extends AbstractChannelNoticeService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.KQPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlOrderId, NoticeTypeEnum noticeTypeEnum) {
|
||||
JSONObject reqParamJSON = getReqParamJSON();
|
||||
JSONObject notifyHead = reqParamJSON.getJSONObject("head");
|
||||
return MutablePair.of(notifyHead.getString("externalRefNumber"), reqParamJSON);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg doNotice(HttpServletRequest request, Object params, PayOrder payOrder, MchAppConfigContext mchAppConfigContext, NoticeTypeEnum noticeTypeEnum) {
|
||||
JSONObject respJson = (JSONObject) JSON.toJSON(params);
|
||||
log.info("快钱回调参数:{}",respJson);
|
||||
boolean verifyResult = verifyParams(respJson, mchAppConfigContext);
|
||||
log.info("快前参数解密结果:{}",respJson);
|
||||
// 验证参数失败
|
||||
if(!verifyResult){
|
||||
throw ResponseException.buildText("签名校验失败");
|
||||
}
|
||||
//验签成功后判断上游订单状态
|
||||
ResponseEntity okResponse = textResp(KqpayKit.resSuccess(respJson));
|
||||
ChannelRetMsg result = new ChannelRetMsg();
|
||||
result.setResponseEntity(okResponse);
|
||||
result.setChannelBizData(respJson);
|
||||
JSONObject requestBody = respJson.getJSONObject("requestBody");
|
||||
KqpayOrderStatus orderStatus = KqpayOrderStatus.getVal(requestBody.getString("orderStatus"));
|
||||
result.setChannelOrderId(requestBody.getString("idOrderCtrl"));
|
||||
result.setPlatformMchOrderNo(requestBody.getString("idTxnCtrl"));
|
||||
result.setChannelErrCode(requestBody.getString("bizResponseCode"));
|
||||
result.setChannelErrMsg(requestBody.getString("bizResponseMessage"));
|
||||
JSONObject equityInfo = requestBody.getJSONObject("equityInfo");
|
||||
result.setPlatformOrderNo(requestBody.getString("channelTradeNo"));
|
||||
result.setChannelUserId(requestBody.getString("thirdPartyBuyerId"));
|
||||
switch (orderStatus){
|
||||
case SUCCESS:
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
break;
|
||||
case FAIL:
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 验证银盛支付通知参数
|
||||
* @return
|
||||
*/
|
||||
public boolean verifyParams(JSONObject jsonParams, MchAppConfigContext mchAppConfigContext) {
|
||||
try {
|
||||
return KqpayKit.checkResultNotify(jsonParams,mchAppConfigContext);
|
||||
}catch (Exception e) {
|
||||
log.error("验证签名异常", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.kqpay;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.RefundOrder;
|
||||
import com.jeequan.jeepay.core.exception.ResponseException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractChannelRefundNoticeService;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.model.KqpayOrderStatus;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 拉卡拉退款回调接口实现类
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2021/12/24 11:31
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class KqpayChannelRefundNoticeService extends AbstractChannelRefundNoticeService {
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.KQPAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlOrderId, NoticeTypeEnum noticeTypeEnum) {
|
||||
try {
|
||||
JSONObject reqParamJSON = getReqParamJSON();
|
||||
JSONObject notifyHead = reqParamJSON.getJSONObject("head");
|
||||
return MutablePair.of(notifyHead.getString("externalRefNumber"), reqParamJSON);
|
||||
} catch (Exception e) {
|
||||
log.error("error", e);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg doNotice(HttpServletRequest request, Object params, RefundOrder refundOrder, MchAppConfigContext mchAppConfigContext, NoticeTypeEnum noticeTypeEnum) {
|
||||
String logPrefix = "【处理快钱退款回调】";
|
||||
try {
|
||||
JSONObject respJson = (JSONObject) JSON.toJSON(params);
|
||||
log.info("快钱回调参数:{}",respJson);
|
||||
boolean verifyResult = verifyParams(respJson, mchAppConfigContext);
|
||||
// 验证参数失败
|
||||
if(!verifyResult){
|
||||
throw ResponseException.buildText("签名校验失败");
|
||||
}
|
||||
log.info("快前参数解密结果:{}",respJson);
|
||||
//验签成功后判断上游订单状态
|
||||
ResponseEntity okResponse = textResp(KqpayKit.resSuccess(respJson));
|
||||
ChannelRetMsg result = new ChannelRetMsg();
|
||||
//验签成功后判断上游订单状态
|
||||
result.setResponseEntity(okResponse);
|
||||
JSONObject requestBody = respJson.getJSONObject("requestBody");
|
||||
KqpayOrderStatus orderStatus = KqpayOrderStatus.getVal(requestBody.getString("orderStatus"));
|
||||
result.setChannelOrderId(requestBody.getString("idOrderCtrl"));
|
||||
result.setPlatformMchOrderNo(requestBody.getString("idTxnCtrl"));
|
||||
result.setChannelErrCode(requestBody.getString("bizResponseCode"));
|
||||
result.setChannelErrMsg(requestBody.getString("bizResponseMessage"));
|
||||
result.setPlatformOrderNo(requestBody.getString("channelTradeNo"));
|
||||
result.setChannelUserId(requestBody.getString("thirdPartyBuyerId"));
|
||||
switch (orderStatus){
|
||||
case SUCCESS:
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
|
||||
break;
|
||||
case FAIL:
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
|
||||
break;
|
||||
default:
|
||||
result.setChannelState(ChannelRetMsg.ChannelState.WAITING);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("error", e);
|
||||
throw ResponseException.buildText("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证快钱退款通知参数
|
||||
* @return
|
||||
*/
|
||||
public boolean verifyParams(JSONObject jsonParams, MchAppConfigContext mchAppConfigContext) {
|
||||
try {
|
||||
return KqpayKit.checkResultNotify(jsonParams,mchAppConfigContext);
|
||||
}catch (Exception e) {
|
||||
log.error("验证签名异常", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
package com.jeequan.jeepay.thirdparty.channel.kqpay;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IGetApplymentDataService;
|
||||
import com.jeequan.jeepay.db.entity.BankBranch;
|
||||
import com.jeequan.jeepay.service.impl.BankBranchService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/***
|
||||
*
|
||||
* @author zx
|
||||
*
|
||||
* @date 2022/1/4 14:54
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class KqpayGetApplymentDataService implements IGetApplymentDataService {
|
||||
|
||||
@Autowired
|
||||
private BankBranchService bankBranchService;
|
||||
|
||||
/**
|
||||
* @cityCode 这里取城市名称.
|
||||
*/
|
||||
@Override
|
||||
public List<JSONObject> getBankBranchInfo(String isvNo, String bankAliasCode, String cityCode, String bankName, String branchName) throws BizException {
|
||||
// Assert.notBlank(bankName, "银行名称不能为空");
|
||||
Page<BankBranch> page = new Page<>();
|
||||
bankBranchService.pageByArea(page, cityCode, bankName, branchName);
|
||||
|
||||
return page.getRecords().stream().map( t -> ((JSONObject) JSON.toJSON(t))).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.kqpay;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.entity.MchInfo;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchAlipayConfigService;
|
||||
import com.jeequan.jeepay.core.model.applyment.ApplymentSignInfo;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.kqpay.KqpayIsvParams;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class KqpayIsvmchAlipayConfigService implements IIsvmchAlipayConfigService {
|
||||
@Override
|
||||
public ApplymentSignInfo alipayOpenSignInfo(MchApplyment mchApplyment) {
|
||||
ApplymentSignInfo result = new ApplymentSignInfo();
|
||||
|
||||
// 进件商户信息
|
||||
// JSONObject suJson = JSON.parseObject(mchApplyment.getSuccResParameter());
|
||||
// if (suJson == null || StringUtils.isEmpty(suJson.getString("huifuId"))) {
|
||||
// result.setState("查询失败");
|
||||
// result.setErrInfo("商户参数为空,该商户还未进件成功");
|
||||
// return result;
|
||||
// }
|
||||
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(mchApplyment);
|
||||
// 服务商配置参数
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
KqpayIsvParams isvParams = (KqpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment.getIsvNo(), mchApplyment.getIfCode());
|
||||
// 渠道拓展地址
|
||||
result.setSignUrl(isvParams.getAliChannelExtUrl());
|
||||
// 图片类型
|
||||
result.setImgType(ApplymentSignInfo.IMG_TYPE_QRCONTENT);
|
||||
result.setState("当前通道无法确定认证状态");
|
||||
|
||||
String succResParameter = mchApplyment.getSuccResParameter();
|
||||
JSONObject succRes = JSON.parseObject(succResParameter);
|
||||
JSONArray alipayList = succRes.getJSONArray("alipayList");
|
||||
if (alipayList.isEmpty()) {
|
||||
result.setState("未报备");
|
||||
} else {
|
||||
JSONObject aliReportData = alipayList.getJSONObject(0);
|
||||
String subMchId = aliReportData.getString("subMchId");
|
||||
if (ObjectUtils.isEmpty(subMchId)) {
|
||||
result.setChannelSubMchId(aliReportData.getString("errorMsg"));
|
||||
} else {
|
||||
result.setChannelSubMchId(subMchId);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.kqpay;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.jeequan.jeepay.core.beans.RequestKitBean;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchApplymentNotifyService;
|
||||
import com.jeequan.jeepay.core.model.params.kqpay.KqpayIsvParams;
|
||||
import com.jeequan.jeepay.db.entity.PayInterfaceConfig;
|
||||
import com.jeequan.jeepay.service.impl.MchApplymentService;
|
||||
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service("kqpayIsvmchApplymentNotifyService")
|
||||
public class KqpayIsvmchApplymentNotifyService implements IIsvmchApplymentNotifyService {
|
||||
|
||||
@Autowired
|
||||
private KqpayMchApplymentService kqpayMchApplymentService;
|
||||
|
||||
@Autowired
|
||||
private PayInterfaceConfigService payInterfaceConfigService;
|
||||
|
||||
@Autowired @Lazy
|
||||
private MchApplymentService mchApplymentService;
|
||||
|
||||
@Autowired
|
||||
protected RequestKitBean requestKitBean;
|
||||
|
||||
@Autowired
|
||||
private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public ResponseEntity<?> retOk(Object params) {
|
||||
JSONObject reqParamJSON = requestKitBean.getReqParamJSON();
|
||||
String s = KqpayKit.resSuccess((reqParamJSON));
|
||||
return ResponseEntity.ok(JSON.parseObject(s));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlApplyId) {
|
||||
|
||||
JSONObject reqParamJSON = requestKitBean.getReqParamJSON();
|
||||
String url = "https://reg.shouyinbeipay.com/auditCallback/kq";
|
||||
HttpResponse execute = null;
|
||||
try {
|
||||
execute = HttpRequest.post(url)
|
||||
.body(reqParamJSON.toJSONString())
|
||||
.execute();
|
||||
if (execute.isOk()) {
|
||||
log.info("回调给{}成功", url);
|
||||
} else {
|
||||
log.info("回调给{}异常", url);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.info("回调给{}异常", url);
|
||||
if (execute != null) {
|
||||
execute.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
String orderId = reqParamJSON.getJSONObject("head").getString("externalRefNumber");
|
||||
com.jeequan.jeepay.db.entity.MchApplyment mchApplyment = mchApplymentService.getByOrderId(orderId);
|
||||
|
||||
String memberCode = reqParamJSON.getJSONObject("head").getString("memberCode");
|
||||
|
||||
QueryWrapper<PayInterfaceConfig> qWrapper = Wrappers.query();
|
||||
qWrapper.eq("if_params->>'$.memberCode'", memberCode);
|
||||
qWrapper.eq("if_code", "kqpay");
|
||||
|
||||
List<PayInterfaceConfig> list = payInterfaceConfigService.list(qWrapper);
|
||||
|
||||
if (list.isEmpty()) {
|
||||
throw new BizException("没找到配置信息");
|
||||
}
|
||||
|
||||
KqpayIsvParams isvParams = JSON.parseObject(list.get(0).getIfParams(), KqpayIsvParams.class);
|
||||
|
||||
log.info("快钱回调: {}", reqParamJSON);
|
||||
|
||||
KqpayKit.checkResultNotify(reqParamJSON, isvParams);
|
||||
|
||||
return new MutablePair<>(mchApplyment.getApplyId(), reqParamJSON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchApplyment, ResponseEntity> doNotify(HttpServletRequest request, Object params, MchApplyment mchApplyment) {
|
||||
MchApplyment resultMch = new MchApplyment();
|
||||
|
||||
JSONObject bizParam = ((JSONObject) params).getJSONObject("requestBody");
|
||||
String status = bizParam.getString("status");
|
||||
|
||||
JSONObject openResult = bizParam.getJSONObject("openResult");
|
||||
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("isReceived", "1");
|
||||
|
||||
ResponseEntity<JSONObject> ok = ResponseEntity.ok(param);
|
||||
|
||||
String comments = bizParam.getString("comments");
|
||||
resultMch.setApplyErrorInfo(comments);
|
||||
if ("REJECTED".equals(status)) {
|
||||
resultMch.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
return new MutablePair<>(resultMch, ok);
|
||||
}
|
||||
|
||||
if ("FINISHED".equals(status)) {
|
||||
resultMch.setChannelMchNo(bizParam.getString("subMerchantId"));
|
||||
resultMch.setSuccResParameter(bizParam.toString());
|
||||
// 收集子商户信息
|
||||
kqpayMchApplymentService.subMchColl(mchApplyment, bizParam);
|
||||
return new MutablePair<>(resultMch, ok);
|
||||
}
|
||||
|
||||
if ("TO_BE_SIGNED".equals(status) ) {
|
||||
KqpayIsvParams isvParams = (KqpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);
|
||||
|
||||
int allowSignResult = kqpayMchApplymentService.isAllowSign(mchApplyment);
|
||||
if (allowSignResult == 2) {
|
||||
resultMch.setState(MchApplyment.STATE_WAIT_SIGN);
|
||||
return new MutablePair<>(resultMch, ok);
|
||||
}
|
||||
|
||||
if (allowSignResult == 1) {
|
||||
kqpayMchApplymentService.signApply(mchApplyment);
|
||||
resultMch = kqpayMchApplymentService.query(mchApplyment);
|
||||
return new MutablePair<>(resultMch, ok);
|
||||
}
|
||||
}
|
||||
|
||||
if ("TO_BE_REAUDITED".equals(status)) {
|
||||
if (openResult != null) {
|
||||
resultMch.setChannelMchNo(openResult.getString("subMerchantId"));
|
||||
resultMch.setSuccResParameter(openResult.toString());
|
||||
kqpayMchApplymentService.subMchColl(mchApplyment, openResult);
|
||||
}
|
||||
resultMch.setState(MchApplyment.STATE_SUCCESS_NEED_SECOND_VERIFY);
|
||||
|
||||
return new MutablePair<>(resultMch, ok);
|
||||
}
|
||||
|
||||
return new MutablePair<>(mchApplyment, ok);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.kqpay;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.entity.MchModifyApplyment;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchModifyApplymentService;
|
||||
import com.jeequan.jeepay.core.model.applyment.KqpayApplymentInfo;
|
||||
import com.jeequan.jeepay.core.model.applyment.MchModifyApplymentModel;
|
||||
import com.jeequan.jeepay.core.model.params.kqpay.KqpayIsvParams;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.model.KqpayResp;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.util.KqpayConst;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class KqpayIsvmchModifyApplymentService implements IIsvmchModifyApplymentService {
|
||||
|
||||
@Autowired
|
||||
private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> localModifyBase(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();
|
||||
MchApplyment resultMchApplyment = new MchApplyment();
|
||||
|
||||
MchModifyApplyment mchModifyApplyment = mchDataPair.getKey();
|
||||
resultModifyApplyment.setModifyApplyId(mchModifyApplyment.getModifyApplyId());
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_SUCCESS);
|
||||
MchApplyment mchApplyment = mchDataPair.getValue();
|
||||
resultMchApplyment.setApplyId(mchApplyment.getApplyId());
|
||||
|
||||
String applyDetailInfo = mchModifyApplyment.getApplyDetailInfo();
|
||||
MchModifyApplymentModel mchModifyData = JSON.parseObject(applyDetailInfo, MchModifyApplymentModel.class);
|
||||
|
||||
String originApplyDetailInfo = mchApplyment.getApplyDetailInfo();
|
||||
KqpayApplymentInfo originMchModifyData = JSON.parseObject(originApplyDetailInfo, KqpayApplymentInfo.class);
|
||||
resultMchApplyment.setApplyDetailInfo(JSON.toJSONString(originMchModifyData));
|
||||
|
||||
originMchModifyData.setMchShortName(mchModifyData.getMchShortName());
|
||||
resultMchApplyment.setMchShortName(mchModifyData.getMchShortName());
|
||||
|
||||
return new MutablePair<>(resultModifyApplyment, resultMchApplyment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> localModifySettlement(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();
|
||||
MchApplyment resultMchApplyment = new MchApplyment();
|
||||
|
||||
MchModifyApplyment mchModifyApplyment = mchDataPair.getKey();
|
||||
resultModifyApplyment.setModifyApplyId(mchModifyApplyment.getModifyApplyId());
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_SUCCESS);
|
||||
MchApplyment mchApplyment = mchDataPair.getValue();
|
||||
resultMchApplyment.setApplyId(mchApplyment.getApplyId());
|
||||
|
||||
String applyDetailInfo = mchModifyApplyment.getApplyDetailInfo();
|
||||
MchModifyApplymentModel mchModifyData = JSON.parseObject(applyDetailInfo, MchModifyApplymentModel.class);
|
||||
|
||||
String originApplyDetailInfo = mchApplyment.getApplyDetailInfo();
|
||||
KqpayApplymentInfo originMchModifyData = JSON.parseObject(originApplyDetailInfo, KqpayApplymentInfo.class);
|
||||
resultMchApplyment.setApplyDetailInfo(JSON.toJSONString(originMchModifyData));
|
||||
|
||||
originMchModifyData.setSettAccountType(mchModifyData.getSettAccountType());
|
||||
originMchModifyData.setIsUncrpSett(mchModifyData.getIllegal());
|
||||
originMchModifyData.setSettAccountLicenseImg(mchModifyData.getSettAccountLicenseImg());
|
||||
originMchModifyData.setSettAccountName(mchModifyData.getSettAccountName());
|
||||
originMchModifyData.setSettAccountNo(mchModifyData.getSettAccountNo());
|
||||
originMchModifyData.setSettAccountBankName(mchModifyData.getSettAccountBankName());
|
||||
originMchModifyData.setPersonalInformationAttorney(mchModifyData.getNonLegSettleAuthPic());
|
||||
originMchModifyData.setSettAccountIdcardNo(mchModifyData.getSettAccountIdcardNo());
|
||||
originMchModifyData.setSettAccountIdcard1Img(mchModifyData.getSettAccountIdcard1Img());
|
||||
originMchModifyData.setSettAccountIdcard2Img(mchModifyData.getSettAccountIdcard2Img());
|
||||
originMchModifyData.setSettAccountIdcardEffectBegin(mchModifyData.getSettAccountIdcardEffectBegin());
|
||||
originMchModifyData.setSettAccountIdcardEffectEnd(mchModifyData.getSettAccountIdcardEffectEnd());
|
||||
|
||||
return new MutablePair<>(resultModifyApplyment, resultMchApplyment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> localModifyRate(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> syncChannelModifyBase(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
throw new BizException("暂不支持该操作");
|
||||
// MchModifyApplyment modifyApplyment = mchDataPair.getLeft();
|
||||
// MchApplyment mchApplyment = mchDataPair.getRight();
|
||||
//
|
||||
// KqpayApplymentInfo kqpayApplymentInfo = JSON.parseObject(mchApplyment.getApplyDetailInfo(), KqpayApplymentInfo.class);
|
||||
//
|
||||
// JSONObject param = new JSONObject();
|
||||
// param.fluentPut("operator", "admin")
|
||||
// .fluentPut("subBillAccount", kqpayApplymentInfo.getContactEmail());
|
||||
//
|
||||
// // 套餐信息
|
||||
// JSONObject packageInfo = new JSONObject();
|
||||
// param.put("packageInfo", packageInfo);
|
||||
// packageInfo.put("packageCode", KqpayConst.Package.COMPANY_BASE_EDIT.getCode());
|
||||
//
|
||||
// String openAccountWillingnessLetter = "https://syb-jq-public.oss-cn-hangzhou.aliyuncs.com/applyment/38835122-55b6-48be-884e-35e4aa856b99.jpg";
|
||||
//
|
||||
// KqpayIsvParams isvParams = (KqpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);
|
||||
// String openAccountWillingnessLetterFssId = KqpayKit.uploadRequest(openAccountWillingnessLetter, isvParams);
|
||||
//
|
||||
// List<Object> additionList = new ArrayList<>();
|
||||
// param.put("additionList", additionList);
|
||||
// Map<String, Object> addition = new HashMap<>();
|
||||
// additionList.add(addition);
|
||||
// addition.put("additionFssId", openAccountWillingnessLetterFssId);
|
||||
// addition.put("additionFileType", "OPEN_ACCOUNT_WILLINGNESS_LETTER");
|
||||
// addition.put("additionRemark", "开户意愿确认函");
|
||||
// addition.put("extName", "jpg");
|
||||
//
|
||||
// KqpayResp kqpayResp = KqpayKit.applymentRequest(KqpayConst.ReqMethod.BS005, isvParams, param);
|
||||
//
|
||||
// return mchDataPair;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> syncChannelModifySettlement(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
MchModifyApplyment resultModifyApplyment = new MchModifyApplyment();
|
||||
MchApplyment resultMchApplyment = new MchApplyment();
|
||||
|
||||
MchModifyApplyment modifyApplyment = mchDataPair.getLeft();
|
||||
resultModifyApplyment.setModifyApplyId(modifyApplyment.getModifyApplyId());
|
||||
MchApplyment mchApplyment = mchDataPair.getRight();
|
||||
resultMchApplyment.setApplyId(mchApplyment.getApplyId());
|
||||
|
||||
KqpayIsvParams isvParams = (KqpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);
|
||||
|
||||
KqpayApplymentInfo kqpayApplymentInfo = JSON.parseObject(mchApplyment.getApplyDetailInfo(), KqpayApplymentInfo.class);
|
||||
|
||||
MchModifyApplymentModel modifyApplyBiz = JSON.parseObject(modifyApplyment.getApplyDetailInfo(), MchModifyApplymentModel.class);
|
||||
|
||||
JSONObject param = new JSONObject();
|
||||
param.fluentPut("operator", "admin")
|
||||
.fluentPut("subBillAccount", kqpayApplymentInfo.getContactEmail());
|
||||
|
||||
// 套餐信息
|
||||
JSONObject packageInfo = new JSONObject();
|
||||
param.put("packageInfo", packageInfo);
|
||||
packageInfo.put("packageCode", KqpayConst.Package.COMPANY_BASE_EDIT.getCode());
|
||||
|
||||
JSONObject packageParam = new JSONObject();
|
||||
packageInfo.put("packageParameter", packageParam);
|
||||
// 定向付款信息域
|
||||
JSONObject settlementInfo = new JSONObject();
|
||||
packageParam.put("packageParam", settlementInfo);
|
||||
settlementInfo.put("bankMobilePhone", modifyApplyBiz.getPhone());
|
||||
if (modifyApplyBiz.getSettAccountType().equals("B")) {
|
||||
settlementInfo.put("accountType", "0");
|
||||
} else {
|
||||
if (modifyApplyBiz.getIllegal().equals("Y")) {
|
||||
settlementInfo.put("accountType", "2");
|
||||
} else {
|
||||
settlementInfo.put("accountType", "1");
|
||||
}
|
||||
}
|
||||
settlementInfo.put("accountNo", modifyApplyBiz.getSettAccountNo());
|
||||
settlementInfo.put("accountName", modifyApplyBiz.getSettAccountName());
|
||||
settlementInfo.put("bankName", modifyApplyBiz.getSettAccountBankName());
|
||||
settlementInfo.put("bankBranch", modifyApplyBiz.getSettAccountBankBranchName());
|
||||
Assert.notNull(modifyApplyBiz.getSettAccountBankBranchAreaCode(), "支行地区编码信息不能为空");
|
||||
Assert.isTrue(modifyApplyBiz.getSettAccountBankBranchAreaCode().size() >= 2, "支行地区编码信息不能为空");
|
||||
settlementInfo.put("areaCode", modifyApplyBiz.getSettAccountBankBranchAreaCode().getString(1));
|
||||
|
||||
if (kqpayApplymentInfo.getMerchantType() != MchApplyment.MERCHANT_TYPE_PERSONAL) {
|
||||
JSONObject accOpenInfo = new JSONObject();
|
||||
packageParam.put("accOpenInfo", accOpenInfo);
|
||||
String accOpenFssId = KqpayKit.uploadRequest(modifyApplyBiz.getAccOpenCertImg(), isvParams);
|
||||
}
|
||||
|
||||
if (modifyApplyBiz.getIllegal().equals("Y")) {
|
||||
JSONObject authorizerInfo = new JSONObject();
|
||||
packageParam.put("authorizerInfo", authorizerInfo);
|
||||
String authFssId = KqpayKit.uploadRequest(modifyApplyBiz.getNonLegSettleAuthPic(), isvParams);
|
||||
authorizerInfo.put("authFssId", authFssId);
|
||||
String idCard1Img = KqpayKit.uploadRequest(modifyApplyBiz.getSettAccountIdcard1Img(), isvParams);
|
||||
authorizerInfo.put("authNationalFssId", idCard1Img);
|
||||
String idCard2Img = KqpayKit.uploadRequest(modifyApplyBiz.getSettAccountIdcard2Img(), isvParams);
|
||||
authorizerInfo.put("authPersonFssId", idCard2Img);
|
||||
authorizerInfo.put("beginDate", modifyApplyBiz.getSettAccountIdcardEffectBegin());
|
||||
authorizerInfo.put("expireDate", modifyApplyBiz.getSettAccountIdcardEffectEnd());
|
||||
authorizerInfo.put("authIdCard", modifyApplyBiz.getSettAccountIdcardNo());
|
||||
authorizerInfo.put("authTel", modifyApplyBiz.getPhone());
|
||||
authorizerInfo.put("authName", modifyApplyBiz.getSettAccountName());
|
||||
String authHandFssId = KqpayKit.uploadRequest(modifyApplyBiz.getAuthHandImg(), isvParams);
|
||||
authorizerInfo.put("authHandFssId", authHandFssId);
|
||||
}
|
||||
|
||||
try {
|
||||
KqpayResp kqpayResp = KqpayKit.applymentRequest(KqpayConst.ReqMethod.BS005, isvParams, param);
|
||||
JSONObject responseBody = kqpayResp.getResponseBody();
|
||||
String bizResponseCode = responseBody.getString("bizResponseCode");
|
||||
String bizResponseMessage = responseBody.getString("bizResponseMessage");
|
||||
|
||||
resultModifyApplyment.setChannelVar1(responseBody.toJSONString());
|
||||
|
||||
if (!KqpayConst.SUCCESS.equals(bizResponseCode)) {
|
||||
resultModifyApplyment.setApplyDetailInfo("[" + bizResponseMessage + "]");
|
||||
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
return new MutablePair<>(resultModifyApplyment, null);
|
||||
}
|
||||
|
||||
String orderId = responseBody.getString("orderId");
|
||||
resultModifyApplyment.setChannelApplyNo(orderId);
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_AUDITING);
|
||||
|
||||
return new MutablePair<>(resultModifyApplyment, null);
|
||||
|
||||
} catch (Exception e) {
|
||||
resultModifyApplyment.setApplyDetailInfo("[" + e.getMessage() + "]");
|
||||
resultModifyApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
|
||||
return new MutablePair<>(resultModifyApplyment, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> syncChannelModifyRate(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> syncChannelModifySettlementType(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutablePair<MchModifyApplyment, MchApplyment> queryModifyResult(MutablePair<MchModifyApplyment, MchApplyment> mchDataPair) {
|
||||
MchModifyApplyment resultMchModifyApplyment = mchDataPair.left;
|
||||
MchApplyment resultMch = mchDataPair.right;
|
||||
|
||||
KqpayIsvParams isvParams = (KqpayIsvParams) configContextQueryService.queryIsvParams(mchDataPair.right);
|
||||
|
||||
JSONObject reqParam = new JSONObject();
|
||||
reqParam.put("orderId", resultMchModifyApplyment.getChannelApplyNo());
|
||||
KqpayResp kqpayResp = KqpayKit.applymentRequest(KqpayConst.ReqMethod.BS002, isvParams, reqParam);
|
||||
JSONObject responseBody = kqpayResp.getResponseBody();
|
||||
String bizResponseCode = responseBody.getString("bizResponseCode");
|
||||
String bizResponseMessage = responseBody.getString("bizResponseMessage");
|
||||
|
||||
|
||||
if (!KqpayConst.SUCCESS.equals(bizResponseCode)) {
|
||||
log.info("快钱查询商户变更审核状态失败, {}", bizResponseMessage);
|
||||
|
||||
return new MutablePair<>();
|
||||
}
|
||||
|
||||
String status = responseBody.getString("status");
|
||||
|
||||
if ("FINISHED".equals(status)) {
|
||||
return localModifySettlement(mchDataPair);
|
||||
}
|
||||
|
||||
return new MutablePair<>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.kqpay;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchWxConfigService;
|
||||
import com.jeequan.jeepay.core.model.applyment.ApplymentSignInfo;
|
||||
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
|
||||
import com.jeequan.jeepay.core.model.params.kqpay.KqpayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class KqpayIsvmchWxConfigService implements IIsvmchWxConfigService {
|
||||
@Override
|
||||
public String queryConfiguredInfo(String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg configBindAppId(String configAppId, String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg configSubscribeAppId(String configAppId, String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg applyModifyMchShortName(String mchShortName, String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg applyModifyMchAppPublicKey(String appPublicKey, String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplymentSignInfo wxOpenSignInfo(MchApplyment mchApplyment) {
|
||||
ApplymentSignInfo result = new ApplymentSignInfo();
|
||||
|
||||
// 获取到 服务商配置信息
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
KqpayIsvParams isvParams = (KqpayIsvParams)configContextQueryService.queryIsvParams(mchApplyment);
|
||||
// 微信开通意愿二维码地址
|
||||
result.setSignUrl(isvParams.getWxOpenUrl());
|
||||
result.setImgType(ApplymentSignInfo.IMG_TYPE_QRCONTENT);
|
||||
|
||||
result.setState("当前通道无法确定认证状态");
|
||||
result.setErrInfo("");
|
||||
|
||||
String succResParameter = mchApplyment.getSuccResParameter();
|
||||
JSONObject succRes = JSON.parseObject(succResParameter);
|
||||
JSONArray alipayList = succRes.getJSONArray("wechatList");
|
||||
if (alipayList.isEmpty()) {
|
||||
result.setState("未报备");
|
||||
} else {
|
||||
JSONObject aliReportData = alipayList.getJSONObject(0);
|
||||
String subMchId = aliReportData.getString("subMchId");
|
||||
if (ObjectUtils.isEmpty(subMchId)) {
|
||||
result.setErrInfo(aliReportData.getString("errorMsg"));
|
||||
} else {
|
||||
result.setChannelSubMchId(subMchId);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg configPayBaseUrl(String configBaseUrl, String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg applyModifyMchRate(List<PaywayFee> paywayFeeList, String isvNo, String mchNo, String mchAppId, String ifCode) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.kqpay;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.bill99.crypto.entity.Bill99CertConfig;
|
||||
import com.bill99.crypto.service.CryptoService;
|
||||
import com.bill99.crypto.service.processor.P7CryptoServiceProcessor;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.params.kqpay.KqpayIsvParams;
|
||||
import com.jeequan.jeepay.core.model.params.kqpay.KqpayIsvsubMchParams;
|
||||
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.model.KqpayReqHead;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.model.KqpayResp;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.util.HttpClientCert;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.util.HttpsClientFactory;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.util.KqpayConst;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Cleanup;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 快钱请求参数
|
||||
*/
|
||||
@Slf4j
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class KqpayKit {
|
||||
|
||||
private static final CryptoService cryptoService = P7CryptoServiceProcessor.getInstance();
|
||||
|
||||
/**
|
||||
* 快钱入网请求网关
|
||||
*/
|
||||
public static final String APPLYMENTS_GATE_WAY = KqpayConst.APPLYMENTS_GATE_WAY;
|
||||
|
||||
public static final String TRADE_GATE_WAY = KqpayConst.TRADE_GATE_WAY;
|
||||
|
||||
|
||||
public static String getExternalRefNumber(String memberCode) {
|
||||
return memberCode + DateUtil.format(new Date(), DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"));
|
||||
}
|
||||
|
||||
public static String uploadRequest(String imgUrl, KqpayIsvParams isvParams) {
|
||||
byte[] imgFileByteArray = HttpUtil.downloadBytes(imgUrl);
|
||||
String base64 = Base64.encode(imgFileByteArray);
|
||||
|
||||
JSONObject reqParam = new JSONObject();
|
||||
reqParam.put("fileBuffer", base64);
|
||||
reqParam.put("fileName", "test.jpg");
|
||||
|
||||
return KqpayKit.applymentRequest(KqpayConst.ReqMethod.BS000, isvParams, reqParam).getResponseBody().getString("fssId");
|
||||
}
|
||||
|
||||
public static KqpayResp applymentRequest(KqpayConst.ReqMethod reqMethod, KqpayIsvParams isvParams, JSONObject bizContent) {
|
||||
String externalRefNumber = ((String) bizContent.remove("externalRefNumber"));
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
Assert.notNull(configContextQueryService, "无法获取快钱入网配置信息");
|
||||
|
||||
KqpayReqHead head = init(reqMethod, isvParams, externalRefNumber);
|
||||
head.setVendorMemberCode(null);
|
||||
try {
|
||||
return reqApi(APPLYMENTS_GATE_WAY, head, bizContent, isvParams);
|
||||
} catch (Exception e) {
|
||||
log.info("快钱入网请求异常,", e);
|
||||
throw new BizException("快钱入网请求异常, " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static KqpayReqHead init(KqpayConst.ReqMethod reqMethod, KqpayIsvParams isvParams, String outFlowNo) {
|
||||
initCert(isvParams);
|
||||
KqpayReqHead head = new KqpayReqHead();
|
||||
head.setVersion("1.0.0");
|
||||
head.setVendorMemberCode(isvParams.getVendorMemberCode());
|
||||
head.setMemberCode(head.getVendorMemberCode());
|
||||
head.setMessageType(reqMethod.getMessageType());
|
||||
if (StringUtils.isNotEmpty(outFlowNo)) {
|
||||
head.setExternalRefNumber(outFlowNo);
|
||||
} else {
|
||||
head.setExternalRefNumber(getExternalRefNumber(isvParams.getVendorMemberCode()));
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
|
||||
public static KqpayResp payRequest(KqpayConst.ReqMethod reqMethod, MchAppConfigContext mchAppConfigContext, JSONObject bizContent, String outFlowNo) {// 配置参数
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
Assert.notNull(configContextQueryService, "无法获取快钱入网配置信息");
|
||||
KqpayIsvParams isvParams = (KqpayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment().getIsvNo(), CS.IF_CODE.KQPAY);
|
||||
|
||||
KqpayReqHead head = init(reqMethod, isvParams, outFlowNo);
|
||||
head.setMemberCode(bizContent.getString("kqCode"));
|
||||
try {
|
||||
return reqApi(TRADE_GATE_WAY, head, bizContent, isvParams);
|
||||
} catch (Exception e) {
|
||||
throw new BizException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置参数
|
||||
*
|
||||
* @param mchAppConfigContext
|
||||
* @param bizContent
|
||||
*/
|
||||
public static void setPayParams(MchAppConfigContext mchAppConfigContext, JSONObject bizContent) {
|
||||
KqpayIsvsubMchParams mchParams = JSON.parseObject(mchAppConfigContext.getMchApplyment().getSuccResParameter(),KqpayIsvsubMchParams.class);
|
||||
bizContent.put("merchantId", mchParams.getSubMerchantId());
|
||||
List<JSONObject> terminalInfos = mchParams.getTerminalInfos();
|
||||
JSONObject item = terminalInfos.stream().filter(e -> "terminalQkf".equals(e.getString("type"))).findFirst().orElse(new JSONObject());
|
||||
JSONArray terminalIds = item.getJSONArray("terminalIds");
|
||||
bizContent.put("terminalId", terminalIds.get(0));
|
||||
bizContent.put("kqCode", mchParams.getSubMemberCode());
|
||||
bizContent.put("cur", "CNY");
|
||||
}
|
||||
|
||||
public static KqpayResp reqApi(String url, KqpayReqHead head, JSONObject bizData, KqpayIsvParams isvParams) throws Exception {
|
||||
JSONObject encryptBody = null;
|
||||
try {
|
||||
encryptBody = cryptoService.seal(bizData.toString());
|
||||
} catch (Exception e) {
|
||||
log.error("请求快钱,加密加签出错。", e);
|
||||
}
|
||||
JSONObject requestString = new JSONObject();
|
||||
requestString.put("head", head);
|
||||
requestString.put("requestBody", encryptBody);
|
||||
log.info("快钱接口请求地址:{}", url);
|
||||
log.info("快钱接口请求业务参数:{}", bizData);
|
||||
log.info("快钱接口请求参数:{}", requestString);
|
||||
@Cleanup CloseableHttpClient httpClient = url.startsWith("https") ? createHttpsClient(isvParams) : HttpClients.createDefault();
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000)
|
||||
.setConnectTimeout(10000).build();
|
||||
httpPost.setConfig(requestConfig);
|
||||
httpPost.setEntity(new StringEntity(requestString.toJSONString(), Consts.UTF_8));
|
||||
return httpClient.execute(httpPost, httpresponse -> {
|
||||
int statusCode = httpresponse.getStatusLine().getStatusCode();
|
||||
if (200 != statusCode) {
|
||||
return null;
|
||||
} else {
|
||||
String entityStr;
|
||||
HttpEntity entity = httpresponse.getEntity();
|
||||
if (null != entity) {
|
||||
entityStr = EntityUtils.toString(entity, Consts.UTF_8);
|
||||
log.info("快钱请求返回待解密报文:{}", entityStr);
|
||||
JSONObject respEncryptObject = JSON.parseObject(entityStr);
|
||||
JSONObject respHead = respEncryptObject.getJSONObject("head");
|
||||
JSONObject respEncryptBody = respEncryptObject.getJSONObject("responseBody");
|
||||
String respSignedData = respEncryptBody.getString("signedData");
|
||||
String respEnvelopedData = respEncryptBody.getString("envelopedData");
|
||||
KqpayResp kqpayResp = new KqpayResp(respHead);
|
||||
if (KqpayConst.SUCCESS.equals(respHead.getString("responseCode"))) {
|
||||
String respDecryptBody = null;
|
||||
try {
|
||||
respDecryptBody = cryptoService.unSeal(respEnvelopedData, respSignedData);
|
||||
log.info("快钱请求返回报文:{}", respDecryptBody);
|
||||
} catch (Exception e) {
|
||||
log.info("快钱入网解密异常", e);
|
||||
}
|
||||
kqpayResp.setResponseBody(JSON.parseObject(respDecryptBody));
|
||||
return kqpayResp;
|
||||
} else {
|
||||
log.error("请求快钱出错, head报错信息 = {}", respHead.toJSONString());
|
||||
throw new BizException(respHead.getString("responseTextMessage"));
|
||||
}
|
||||
} else {
|
||||
throw new BizException("接口请求异常");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static CloseableHttpClient createHttpsClient(KqpayIsvParams kqpayIsvParams) throws Exception {
|
||||
ChannelCertConfigKitBean channelCertConfigKitBean = SpringBeansUtil.getBean(ChannelCertConfigKitBean.class);
|
||||
String certFilePath = channelCertConfigKitBean.getCertFilePath(kqpayIsvParams.getSslPublicPath());
|
||||
|
||||
@Cleanup InputStream keystoreFileInputStream = new FileInputStream(certFilePath);
|
||||
|
||||
KeyStore keyStore = KeyStore.getInstance("PKCS12");
|
||||
keyStore.load(keystoreFileInputStream, kqpayIsvParams.getStorePwd().toCharArray());
|
||||
HttpClientCert httpClientCert = new HttpClientCert();
|
||||
httpClientCert.setKeyStore(keyStore);
|
||||
httpClientCert.setKeyStorePwd(kqpayIsvParams.getStorePwd());
|
||||
httpClientCert.setConnTimeout(60000);
|
||||
httpClientCert.setSoTimeout(10000);
|
||||
httpClientCert.setSSLVersion("TLSv1.2");
|
||||
HttpsClientFactory factory = new HttpsClientFactory();
|
||||
return factory.createSSLClient(httpClientCert);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解析异步通知参数
|
||||
*
|
||||
* @param resNotify
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkResultNotify(JSONObject resNotify, KqpayIsvParams isvParams) {
|
||||
try {
|
||||
initCert(isvParams);
|
||||
JSONObject requestBody = resNotify.getJSONObject("requestBody");
|
||||
String signedData = requestBody.getString("signedData");
|
||||
String envelopedData = requestBody.getString("envelopedData");
|
||||
String data = cryptoService.unSeal(envelopedData, signedData);
|
||||
resNotify.put("requestBody", JSON.parseObject(data));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析异步通知参数
|
||||
*
|
||||
* @param resNotify
|
||||
* @return
|
||||
*/
|
||||
public static boolean checkResultNotify(JSONObject resNotify, MchAppConfigContext mchAppConfigContext) {
|
||||
try {
|
||||
initCert(mchAppConfigContext);
|
||||
JSONObject requestBody = resNotify.getJSONObject("requestBody");
|
||||
String signedData = requestBody.getString("signedData");
|
||||
String envelopedData = requestBody.getString("envelopedData");
|
||||
String data = cryptoService.unSeal(envelopedData, signedData);
|
||||
resNotify.put("requestBody", JSON.parseObject(data));
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装快钱异步通知返回参数
|
||||
*
|
||||
* @param notifyParams
|
||||
* @return
|
||||
*/
|
||||
public static String resSuccess(JSONObject notifyParams) {
|
||||
JSONObject responseBody = new JSONObject(1);
|
||||
responseBody.put("isReceived", "1");
|
||||
try {
|
||||
JSONObject respEncryptBody = cryptoService.seal(responseBody.toJSONString());
|
||||
JSONObject respMessage = new JSONObject();
|
||||
respMessage.put("head", notifyParams.getJSONObject("head"));
|
||||
respMessage.put("responseBody", respEncryptBody);
|
||||
return StringEscapeUtils.unescapeJson(respMessage.toJSONString());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "error";
|
||||
}
|
||||
|
||||
public static KqpayIsvParams initCert(MchAppConfigContext configContext) {
|
||||
ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
|
||||
Assert.notNull(configContextQueryService, "无法获取快钱入网配置信息");
|
||||
KqpayIsvParams isvParams = (KqpayIsvParams) configContextQueryService.queryIsvParams(configContext.getMchApplyment().getIsvNo(), CS.IF_CODE.KQPAY);
|
||||
return initCert(isvParams);
|
||||
}
|
||||
|
||||
public static KqpayIsvParams initCert(KqpayIsvParams isvParams) {
|
||||
ChannelCertConfigKitBean channelCertConfigKitBean = SpringBeansUtil.getBean(ChannelCertConfigKitBean.class);
|
||||
Assert.notNull(channelCertConfigKitBean, "无法获取快钱入网配置文件");
|
||||
String bill99DefaultPublicPath = channelCertConfigKitBean.getCertFilePath(isvParams.getBill99DefaultPublicPath());
|
||||
String merchantDefaultPrivatePath = channelCertConfigKitBean.getCertFilePath(isvParams.getMerchantDefaultPrivatePath());
|
||||
|
||||
Bill99CertConfig bill99CertConfig = new Bill99CertConfig();
|
||||
bill99CertConfig.setBill99DefaultPublicPath(bill99DefaultPublicPath);
|
||||
bill99CertConfig.setMerchantDefaultPrivatePassword(isvParams.getMerchantDefaultPrivatePassword());
|
||||
bill99CertConfig.setMerchantDefaultPrivatePath(merchantDefaultPrivatePath);
|
||||
cryptoService.setBill99CertConfig(bill99CertConfig);
|
||||
return isvParams;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.kqpay;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
|
||||
import com.jeequan.jeepay.core.model.params.IsvParams;
|
||||
import com.jeequan.jeepay.core.model.rqrs.mch.ChannelMchRq;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.core.model.rqrs.settle.ChannelSettleRq;
|
||||
import com.jeequan.jeepay.thirdparty.channel.AbstractMchApiService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.MutablePair;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @author crystal
|
||||
* @date 2023/12/4 10:47
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class KqpayMchApiService extends AbstractMchApiService {
|
||||
|
||||
|
||||
@Override
|
||||
public String getIfCode() {
|
||||
return CS.IF_CODE.KQPAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否支持当前接口 false 不支持
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean preCheck() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param applyment
|
||||
* @param mchRq
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ChannelRetMsg appidAndPath(MchApplyment applyment, ChannelMchRq mchRq) {
|
||||
throw new BizException("快钱通道暂不支持线上操作方式,请联系客服报备处理");
|
||||
}
|
||||
|
||||
/**
|
||||
* 结算记录查询
|
||||
* @param settleRq
|
||||
* @param isvNo
|
||||
* @param isvParams
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<JSONObject> querySettleInfo(ChannelSettleRq settleRq, String isvNo, IsvParams isvParams) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,772 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.kqpay;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.converter.MchInfoConverter;
|
||||
import com.jeequan.jeepay.core.constants.CS;
|
||||
import com.jeequan.jeepay.core.entity.MchApplyment;
|
||||
import com.jeequan.jeepay.core.entity.MchInfo;
|
||||
import com.jeequan.jeepay.core.entity.MchSubInfo;
|
||||
import com.jeequan.jeepay.core.exception.BizException;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchApplymentService;
|
||||
import com.jeequan.jeepay.core.model.applyment.ApplymentBasicInfo;
|
||||
import com.jeequan.jeepay.core.model.applyment.ApplymentSignInfo;
|
||||
import com.jeequan.jeepay.core.model.applyment.KqpayApplymentInfo;
|
||||
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.oauth2.AlipayOauth2Params;
|
||||
import com.jeequan.jeepay.core.model.oauth2.WxpayOauth2Params;
|
||||
import com.jeequan.jeepay.core.model.params.kqpay.KqpayIsvParams;
|
||||
import com.jeequan.jeepay.db.entity.MchSubInfoEntity;
|
||||
import com.jeequan.jeepay.service.impl.MchSubInfoService;
|
||||
import com.jeequan.jeepay.service.impl.SysConfigService;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.model.KqpayResp;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.util.KqpayConst;
|
||||
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* 快钱商户入网审批流程
|
||||
* 调用BS008,获取个人信息同意授权书等官方电子版数据
|
||||
* 新商户进件申请成功,此时调BS002,返的是 审批中 ,
|
||||
* 审批完成后查询到的是 合同待签约(不能直接签约,需要激活快钱,签约前可以调合同查询接口,如果是0-待签约 才能调签约接口)
|
||||
* 签约完成后,调BS002 返的是 已完成,至此进件完成
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class KqpayMchApplymentService implements IIsvmchApplymentService<KqpayApplymentInfo> {
|
||||
|
||||
@Autowired
|
||||
private SysConfigService sysConfigService;
|
||||
|
||||
@Autowired
|
||||
private ConfigContextQueryService configContextQueryService;
|
||||
|
||||
@Autowired
|
||||
private MchSubInfoService mchSubInfoService;
|
||||
|
||||
@Autowired
|
||||
private MchInfoConverter mchInfoConverter;
|
||||
|
||||
/**
|
||||
* 开户意愿确认, 入网前的操作
|
||||
*
|
||||
* @param mchApplyment
|
||||
*/
|
||||
public void willingnessConfirm(MchApplyment mchApplyment, KqpayApplymentInfo applymentInfo, KqpayIsvParams isvParams) {
|
||||
JSONObject bizContent = new JSONObject();
|
||||
bizContent.put("legalId", applymentInfo.getIdcardNo());
|
||||
bizContent.put("legalName", applymentInfo.getIdcardName());
|
||||
|
||||
if (applymentInfo.getMerchantType() != MchApplyment.MERCHANT_TYPE_PERSONAL) {
|
||||
// 营业执照信息
|
||||
bizContent.put("businessLicense", applymentInfo.getLicenseNo());
|
||||
bizContent.put("merchantType", "1");
|
||||
|
||||
if (applymentInfo.getIsUncrpSett().equals("Y")) {
|
||||
bizContent.put("settleToAuth", "1");
|
||||
bizContent.put("authName", applymentInfo.getSettAccountName());
|
||||
bizContent.put("authIdCard", applymentInfo.getSettAccountIdcardNo());
|
||||
}
|
||||
} else {
|
||||
bizContent.put("merchantType", "2");
|
||||
}
|
||||
|
||||
bizContent.put("merchantName", applymentInfo.getMchFullName());
|
||||
|
||||
List<String> fileTypeList = new ArrayList<>();
|
||||
bizContent.put("fileTypeList", fileTypeList);
|
||||
fileTypeList.add("OPEN_ACCOUNT_WILLINGNESS_LETTER");
|
||||
fileTypeList.add("SPE_MERCH_SQSDZRGZS");
|
||||
fileTypeList.add("PERSONAL_INFORMATION_ATTORNEY");
|
||||
|
||||
KqpayResp kqpayResp = KqpayKit.applymentRequest(KqpayConst.ReqMethod.BS008, isvParams, bizContent);
|
||||
JSONObject responseBody = kqpayResp.getResponseBody();
|
||||
|
||||
String bizResponseCode = responseBody.getString("bizResponseCode");
|
||||
String bizResponseMessage = responseBody.getString("bizResponseMessage");
|
||||
|
||||
if (!KqpayConst.SUCCESS.equals(bizResponseCode)) {
|
||||
log.info("快钱开户意愿确认接口调用失败, {}", bizResponseMessage);
|
||||
throw new BizException("快钱开户意愿确认失败, " + bizResponseMessage);
|
||||
}
|
||||
|
||||
JSONArray data = responseBody.getJSONArray("data");
|
||||
mchApplyment.setChannelVar1(data.toJSONString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图片,入网时候
|
||||
*
|
||||
* @param uploadResultMap 上传图片返回结果
|
||||
* @param imgUrl 图片链接
|
||||
* @param isvParams 通道服务商配置参数
|
||||
*/
|
||||
public void uploadRequest(Map<String, Future<String>> uploadResultMap, String key, String imgUrl, KqpayIsvParams isvParams, Consumer<String> consumer) {
|
||||
// 下载文件
|
||||
if (ObjectUtils.isEmpty(imgUrl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 改为同步请求
|
||||
String fssId = KqpayKit.uploadRequest(imgUrl, isvParams);
|
||||
consumer.accept(fssId);
|
||||
|
||||
// Future<String> submit = executorService.submit(() -> {
|
||||
// String fssId = KqpayKit.uploadRequest(imgUrl, isvParams);
|
||||
// consumer.accept(fssId);
|
||||
// return fssId;
|
||||
// });
|
||||
//
|
||||
// uploadResultMap.put(key, submit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.jeequan.jeepay.core.entity.MchApplyment firstApplyment(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
|
||||
// 直接丢到异步处理进件逻辑
|
||||
mchApplyment.setState(com.jeequan.jeepay.core.entity.MchApplyment.STATE_AUDITING_WAIT);
|
||||
mchApplyment.setRemainStep((byte) 1);
|
||||
mchApplyment.setSettlementType(CS.SETTLEMENT_TYPE.T1);
|
||||
|
||||
return mchApplyment;
|
||||
}
|
||||
|
||||
|
||||
public JSONObject getApplymentParams(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment, KqpayIsvParams isvParams) {
|
||||
|
||||
String applyDetailInfo = mchApplyment.getApplyDetailInfo();
|
||||
|
||||
Map<String, Future<String>> uploadResultMap = new HashMap<>();
|
||||
|
||||
log.info("商户信息: {}", applyDetailInfo);
|
||||
if (applyDetailInfo == null || applyDetailInfo.isEmpty()) {
|
||||
throw new BizException("无法获取到商户信息");
|
||||
}
|
||||
|
||||
KqpayApplymentInfo mchInfoSrc = JSON.parseObject(applyDetailInfo, KqpayApplymentInfo.class);
|
||||
|
||||
willingnessConfirm(mchApplyment, mchInfoSrc, isvParams);
|
||||
|
||||
JSONObject mchInfoDes = new JSONObject();
|
||||
mchInfoDes.put("operator", "admin");
|
||||
Assert.notNull(mchInfoSrc.getContactEmail(), "缺少电子邮箱");
|
||||
mchInfoDes.put("subBillAccount", mchInfoSrc.getContactEmail());
|
||||
// 结算信息
|
||||
mchInfoDes.put("settlementInfo", getSettlement(uploadResultMap, mchInfoSrc, isvParams));
|
||||
|
||||
// 主体信息
|
||||
JSONObject subjectInfo = getSubjectInfo(uploadResultMap, mchInfoSrc, isvParams);
|
||||
|
||||
mchInfoDes.put("subjectInfo", subjectInfo);
|
||||
|
||||
// 经营信息
|
||||
mchInfoDes.put("storeInfo", getStoreInfo(uploadResultMap, mchInfoSrc, isvParams));
|
||||
|
||||
// 套餐信息
|
||||
mchInfoDes.put("packageInfo", getPackageInfo(mchInfoSrc, mchApplyment));
|
||||
|
||||
List<JSONObject> additionList = new ArrayList<>();
|
||||
mchInfoDes.put("additionList", additionList);
|
||||
|
||||
JSONArray jsonArray = JSON.parseArray(mchApplyment.getChannelVar1());
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
JSONObject item = jsonArray.getJSONObject(i);
|
||||
String fileName = item.getString("fileName");
|
||||
String fssId = item.getString("fssId");
|
||||
String fileType = item.getString("fileType");
|
||||
|
||||
JSONObject finalAddition = new JSONObject();
|
||||
finalAddition.put("additionFssId", fssId);
|
||||
finalAddition.put("additionFileType", fileType);
|
||||
finalAddition.put("additionRemark", fileName);
|
||||
finalAddition.put("extName", "jpg");
|
||||
additionList.add(finalAddition);
|
||||
}
|
||||
|
||||
// 开户意愿函走电子协议
|
||||
// if (!ObjectUtils.isEmpty(mchInfoSrc.getOpenAccountWillingnessLetter())) {
|
||||
// JSONObject finalAddition = new JSONObject();
|
||||
// uploadRequest(uploadResultMap, "OPEN_ACCOUNT_WILLINGNESS_LETTER", mchInfoSrc.getOpenAccountWillingnessLetter(), isvParams, s -> {
|
||||
// finalAddition.put("additionFssId", s);
|
||||
// });
|
||||
// finalAddition.put("additionFileType", "OPEN_ACCOUNT_WILLINGNESS_LETTER");
|
||||
// finalAddition.put("additionRemark", "开户意愿确认函");
|
||||
// finalAddition.put("extName", "jpg");
|
||||
// additionList.add(finalAddition);
|
||||
// }
|
||||
// 电子协议
|
||||
// if ("C".equals(mchInfoSrc.getSettAccountType())) {
|
||||
// // 个人信息单独同意授权书
|
||||
// JSONObject finalAddition2 = new JSONObject();
|
||||
// uploadRequest(uploadResultMap, "PERSONAL_INFORMATION_ATTORNEY", mchInfoSrc.getPersonalInformationAttorney(), isvParams, s -> {
|
||||
// finalAddition2.put("additionFssId", s);
|
||||
// });
|
||||
// finalAddition2.put("additionFileType", "PERSONAL_INFORMATION_ATTORNEY");
|
||||
// finalAddition2.put("additionRemark", "个人信息单独同意授权书");
|
||||
// finalAddition2.put("extName", "jpg");
|
||||
// additionList.add(finalAddition2);
|
||||
// }
|
||||
|
||||
// uploadResultMap.forEach((key, value) -> {
|
||||
// try {
|
||||
// value.get();
|
||||
// } catch (InterruptedException | ExecutionException e) {
|
||||
// log.info("上传图片异常", e);
|
||||
// throw new BizException("上传图片异常");
|
||||
// }
|
||||
// });
|
||||
|
||||
return mchInfoDes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 主体信息
|
||||
*/
|
||||
private JSONObject getSubjectInfo(Map<String, Future<String>> uploadResultMap, KqpayApplymentInfo mchInfoSrc, KqpayIsvParams isvParams) {
|
||||
JSONObject subjectInfo = new JSONObject();
|
||||
|
||||
subjectInfo.put("merchantShortName", mchInfoSrc.getMchShortName());
|
||||
if (mchInfoSrc.getMerchantType() == 1) {
|
||||
subjectInfo.put("subjectType", "0");
|
||||
} else if (mchInfoSrc.getMerchantType() == 2) {
|
||||
subjectInfo.put("subjectType", "5");
|
||||
} else {
|
||||
subjectInfo.put("subjectType", "1");
|
||||
}
|
||||
|
||||
// 主体信息——营业执照信息
|
||||
if (mchInfoSrc.getMerchantType() != com.jeequan.jeepay.core.entity.MchApplyment.MERCHANT_TYPE_PERSONAL) {
|
||||
subjectInfo.put("businessLicenseInfo", getBusinessLicenseInfo(uploadResultMap, mchInfoSrc, isvParams));
|
||||
}
|
||||
|
||||
if (com.jeequan.jeepay.core.entity.MchApplyment.MERCHANT_TYPE_ENTERPRISE == mchInfoSrc.getMerchantType()) {
|
||||
subjectInfo.put("accOpenInfo", getAccOpenInfo(uploadResultMap, mchInfoSrc, isvParams));
|
||||
}
|
||||
|
||||
// 法人信息
|
||||
subjectInfo.put("identityInfo", getIdentityInfo(uploadResultMap, mchInfoSrc, isvParams));
|
||||
return subjectInfo;
|
||||
}
|
||||
|
||||
private JSONObject getAccOpenInfo(Map<String, Future<String>> uploadResultMap, KqpayApplymentInfo mchInfoSrc, KqpayIsvParams isvParams) {
|
||||
JSONObject accOpenInfo = new JSONObject();
|
||||
|
||||
Assert.notEmpty(mchInfoSrc.getCompanyAccountLicenseImg(), "对公结算, 开户许可证不能为空");
|
||||
// 开户凭证
|
||||
uploadRequest(uploadResultMap, "accOpenFssId", mchInfoSrc.getCompanyAccountLicenseImg(), isvParams, s -> accOpenInfo.put("accOpenFssId", s));
|
||||
accOpenInfo.put("accOpenCode", mchInfoSrc.getAccOpenCode());
|
||||
accOpenInfo.put("accOpenPeriodBegin", mchInfoSrc.getAccOpenPeriodBegin());
|
||||
accOpenInfo.put("accOpenPeriodEnd", mchInfoSrc.getAccOpenPeriodEnd());
|
||||
return accOpenInfo;
|
||||
}
|
||||
|
||||
private JSONObject getBusinessLicenseInfo(Map<String, Future<String>> uploadResultMap, KqpayApplymentInfo mchInfoSrc, KqpayIsvParams isvParams) {
|
||||
JSONObject businessLicenseInfo = new JSONObject();
|
||||
businessLicenseInfo.put("businessRegno", mchInfoSrc.getLicenseNo());
|
||||
businessLicenseInfo.put("merchantName", mchInfoSrc.getMchFullName());
|
||||
businessLicenseInfo.put("legalName", mchInfoSrc.getIdcardName());
|
||||
uploadRequest(uploadResultMap, "fssId", mchInfoSrc.getLicenseImg(), isvParams, s -> businessLicenseInfo.put("fssId", s));
|
||||
businessLicenseInfo.put("constraintBusiness", mchInfoSrc.getLicenseScope());
|
||||
businessLicenseInfo.put("areaCode", mchInfoSrc.getAreaCode().getString(2));
|
||||
businessLicenseInfo.put("address", mchInfoSrc.getLicenseAddress());
|
||||
businessLicenseInfo.put("handleDate", mchInfoSrc.getLicenseEffectBegin());
|
||||
if (ApplymentBasicInfo.DATE_FOREVER_VAL.equals(mchInfoSrc.getLicenseEffectEnd())) {
|
||||
businessLicenseInfo.put("cancelDate", "9999-12-31");
|
||||
} else {
|
||||
businessLicenseInfo.put("cancelDate", mchInfoSrc.getLicenseEffectEnd());
|
||||
}
|
||||
return businessLicenseInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 经营信息
|
||||
*/
|
||||
private JSONObject getStoreInfo(Map<String, Future<String>> uploadResultMap, KqpayApplymentInfo mchInfoSrc, KqpayIsvParams isvParams) {
|
||||
JSONObject storeInfo = new JSONObject();
|
||||
|
||||
storeInfo.put("storeName", mchInfoSrc.getMchFullName());
|
||||
storeInfo.put("areaCode", mchInfoSrc.getAreaCode().getString(2));
|
||||
storeInfo.put("address", mchInfoSrc.getAddress());
|
||||
storeInfo.put("outStoreName", mchInfoSrc.getMchShortName());
|
||||
|
||||
// 经营图片
|
||||
uploadRequest(uploadResultMap, "headFssId", mchInfoSrc.getStoreOuterImg(), isvParams, s -> storeInfo.put("headFssId", s));
|
||||
|
||||
uploadRequest(uploadResultMap, "cashierFssId", mchInfoSrc.getStoreCashierImg(), isvParams, s -> storeInfo.put("cashierFssId", s));
|
||||
|
||||
uploadRequest(uploadResultMap, "inDoorFssId", mchInfoSrc.getStoreInnerImg(), isvParams, s -> storeInfo.put("inDoorFssId", s));
|
||||
|
||||
// String cashierFssId = uploadRequest(mchInfoSrc.getStoreOuterImg(), mchApplyment.getIsvNo());
|
||||
// storeInfo.put("headFssId", cashierFssId);
|
||||
// String cashierFssId = uploadRequest(mchInfoSrc.getStoreCashierImg(), mchApplyment.getIsvNo());
|
||||
// storeInfo.put("cashierFssId", cashierFssId);
|
||||
// String inDoorFssId = uploadRequest(mchInfoSrc.getStoreInnerImg(), mchApplyment.getIsvNo());
|
||||
// storeInfo.put("inDoorFssId", inDoorFssId);
|
||||
return storeInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 法人信息
|
||||
*/
|
||||
private JSONObject getIdentityInfo(Map<String, Future<String>> uploadResultMap, KqpayApplymentInfo mchInfoSrc, KqpayIsvParams isvParams) {
|
||||
JSONObject identityInfo = new JSONObject();
|
||||
identityInfo.put("telephone", mchInfoSrc.getContactPhone());
|
||||
identityInfo.put("idType", "1");
|
||||
if (mchInfoSrc.getMerchantType() == com.jeequan.jeepay.core.entity.MchApplyment.MERCHANT_TYPE_PERSONAL) {
|
||||
identityInfo.put("merchantName", mchInfoSrc.getAddress() + mchInfoSrc.getIdcardName() + mchInfoSrc.getMchShortName());
|
||||
identityInfo.put("address", mchInfoSrc.getAddress());
|
||||
identityInfo.put("areaCode", mchInfoSrc.getAreaCode().getString(2));
|
||||
identityInfo.put("constraintBusiness", mchInfoSrc.getLicenseScope());
|
||||
}
|
||||
|
||||
JSONObject idCardInfo = new JSONObject();
|
||||
identityInfo.put("idCardInfo", idCardInfo);
|
||||
idCardInfo.put("idCardName", mchInfoSrc.getIdcardName());
|
||||
idCardInfo.put("idCardNumber", mchInfoSrc.getIdcardNo());
|
||||
idCardInfo.put("beginDate", mchInfoSrc.getIdcardEffectBegin());
|
||||
if (ApplymentBasicInfo.DATE_FOREVER_VAL.equals(mchInfoSrc.getIdcardEffectEnd())) {
|
||||
idCardInfo.put("expireDate", "9999-12-31");
|
||||
} else {
|
||||
idCardInfo.put("expireDate", mchInfoSrc.getIdcardEffectEnd());
|
||||
}
|
||||
// 法人身份证图片
|
||||
uploadRequest(uploadResultMap, "cardPersonFssId", mchInfoSrc.getIdcard1Img(), isvParams, s -> idCardInfo.put("cardPersonFssId", s));
|
||||
|
||||
uploadRequest(uploadResultMap, "cardNationalFssId", mchInfoSrc.getIdcard2Img(), isvParams, s -> idCardInfo.put("cardNationalFssId", s));
|
||||
// String cardPersonFssId = uploadRequest(mchInfoSrc.getIdcard1Img(), mchApplyment.getIsvNo());
|
||||
// idCardInfo.put("cardPersonFssId", cardPersonFssId);
|
||||
// String cardNationalFssId = uploadRequest(mchInfoSrc.getIdcard2Img(), mchApplyment.getIsvNo());
|
||||
// idCardInfo.put("cardNationalFssId", cardNationalFssId);
|
||||
|
||||
if ("Y".equals(mchInfoSrc.getIsUncrpSett())) {
|
||||
JSONObject authorizerInfo = new JSONObject();
|
||||
identityInfo.put("authorizerInfo", authorizerInfo);
|
||||
authorizerInfo.put("authName", mchInfoSrc.getSettAccountName());
|
||||
authorizerInfo.put("authIdCard", mchInfoSrc.getSettAccountIdcardNo());
|
||||
authorizerInfo.put("beginDate", mchInfoSrc.getSettAccountIdcardEffectBegin());
|
||||
if (ApplymentBasicInfo.DATE_FOREVER_VAL.equals(mchInfoSrc.getSettAccountIdcardEffectEnd())) {
|
||||
authorizerInfo.put("expireDate", "9999-12-31");
|
||||
} else {
|
||||
authorizerInfo.put("expireDate", mchInfoSrc.getSettAccountIdcardEffectEnd());
|
||||
}
|
||||
authorizerInfo.put("authName", mchInfoSrc.getSettAccountName());
|
||||
// 上传结算人身份证
|
||||
uploadRequest(uploadResultMap, "authPersonFssId", mchInfoSrc.getSettAccountIdcard1Img(), isvParams, s -> authorizerInfo.put("authPersonFssId", s));
|
||||
uploadRequest(uploadResultMap, "authNationalFssId", mchInfoSrc.getSettAccountIdcard2Img(), isvParams, s -> authorizerInfo.put("authNationalFssId", s));
|
||||
// String authPersonFssId = uploadRequest(mchInfoSrc.getSettAccountIdcard1Img(), mchApplyment.getIsvNo());
|
||||
// authorizerInfo.put("cardPersonFssId", authPersonFssId);
|
||||
// String authNationalFssId = uploadRequest(mchInfoSrc.getSettAccountIdcard2Img(), mchApplyment.getIsvNo());
|
||||
// authorizerInfo.put("cardNationalFssId", authNationalFssId);
|
||||
|
||||
authorizerInfo.put("authTel", mchInfoSrc.getBankMobile());
|
||||
// 授权证明
|
||||
uploadRequest(uploadResultMap, "authFssId", mchInfoSrc.getPersonalInformationAttorney(), isvParams, s -> authorizerInfo.put("authFssId", s));
|
||||
}
|
||||
|
||||
return identityInfo;
|
||||
}
|
||||
|
||||
private JSONObject getSettlement(Map<String, Future<String>> uploadResultMap, KqpayApplymentInfo mchInfoSrc, KqpayIsvParams isvParams) {
|
||||
JSONObject settlementInfo = new JSONObject();
|
||||
|
||||
settlementInfo.put("settlePan", mchInfoSrc.getSettAccountNo());
|
||||
settlementInfo.put("bankName", mchInfoSrc.getSettAccountBankName());
|
||||
settlementInfo.put("branchName", mchInfoSrc.getSettAccountBankBranchName());
|
||||
settlementInfo.put("areaCode", mchInfoSrc.getSettAccountBankBranchAreaCode().getString(2));
|
||||
if ("Y".equals(mchInfoSrc.getIsUncrpSett())) {
|
||||
// 非法人结算
|
||||
settlementInfo.put("accountName", mchInfoSrc.getSettAccountName());
|
||||
settlementInfo.put("bankMobilePhone", mchInfoSrc.getBankMobile());
|
||||
} else {
|
||||
settlementInfo.put("bankMobilePhone", mchInfoSrc.getLegalPersonPhone());
|
||||
String accountName = "C".equals(mchInfoSrc.getSettAccountType()) ? mchInfoSrc.getIdcardName() : mchInfoSrc.getMchFullName();
|
||||
settlementInfo.put("accountName", accountName);
|
||||
}
|
||||
|
||||
if ("C".equals(mchInfoSrc.getSettAccountType())) {
|
||||
if ("Y".equals(mchInfoSrc.getIsUncrpSett())) {
|
||||
// 授权人结算
|
||||
settlementInfo.put("settleAcctType", "2");
|
||||
} else {
|
||||
// 法人对私结算
|
||||
settlementInfo.put("settleAcctType", "1");
|
||||
}
|
||||
// 对私上传结算卡
|
||||
String cardFssId = KqpayKit.uploadRequest(mchInfoSrc.getSettAccountLicenseImg(), isvParams);
|
||||
settlementInfo.put("cardFssId", cardFssId);
|
||||
// uploadRequest(uploadResultMap, "cardFssId", mchInfoSrc.getSettAccountLicenseImg(), isvParams, s -> settlementInfo.put("cardFssId", s));
|
||||
} else {
|
||||
// 对公,开户许可证在主体信息中已经上传
|
||||
settlementInfo.put("settleAcctType", "0");
|
||||
}
|
||||
|
||||
return settlementInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 【微信】
|
||||
* 微信商户号ID(wechatMchID):1502807381(快钱固定值)
|
||||
* 微信公众号ID(wechatAppID):wxc81c4ae33fe525f0(快钱固定值)
|
||||
* 微信渠道号ID(wechatChannelID):销售前缘申请提供,示例:178354903
|
||||
* 微信关联appId(wechatSubAppId):商户微信应用id,示例:wx9a9e46c300ca733e
|
||||
* 微信支付目录(wechatJsapi):商户支付目录地址,示例:https://www.99bill.com/
|
||||
* 【支付宝】
|
||||
* 支付宝APPID(aliAppID):1266000048120000 (快钱固定值)
|
||||
* 支付宝PID(aliSource):2088821475893827(快钱固定值)
|
||||
* 支付宝SOURCE(aliPid):2088821475893827(可以使用快钱的SOURCE或商户自己的)
|
||||
*/
|
||||
private JSONObject getPackageInfo(KqpayApplymentInfo kqpayApplymentInfo, com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
|
||||
Byte merchantType = kqpayApplymentInfo.getMerchantType();
|
||||
JSONObject packInfo = new JSONObject();
|
||||
|
||||
KqpayConst.Package usePackage = merchantType == 1 ? KqpayConst.Package.MICRO : KqpayConst.Package.COMPANY_AUTO_ACTIVATION;
|
||||
packInfo.put("packageCode", usePackage.getCode());
|
||||
|
||||
JSONObject parameter = new JSONObject();
|
||||
packInfo.put("packageParameter", parameter);
|
||||
parameter.put("mcc", kqpayApplymentInfo.getMccCode());
|
||||
|
||||
BigDecimal bigDecimal100 = new BigDecimal("100");
|
||||
|
||||
List<PaywayFee> paywayFeeList = kqpayApplymentInfo.getPaywayFeeList();
|
||||
if (CollUtil.isEmpty(paywayFeeList)) {
|
||||
throw new BizException("缺少商户费率信息");
|
||||
}
|
||||
paywayFeeList.forEach(item -> {
|
||||
if (item.getWayCode().equals(CS.PAY_WAY_CODE.ALI_JSAPI)) {
|
||||
parameter.put("zhifubaoRate", item.getFeeRate().multiply(bigDecimal100).stripTrailingZeros().toPlainString());
|
||||
}
|
||||
|
||||
if (item.getWayCode().equals(CS.PAY_WAY_CODE.ALI_JSAPI)) {
|
||||
parameter.put("weixinRate", item.getFeeRate().multiply(bigDecimal100).stripTrailingZeros().toPlainString());
|
||||
}
|
||||
|
||||
if (item.getWayCode().equals(CS.PAY_WAY_CODE.YSF_JSAPI)) {
|
||||
String feeType = item.getFeeType();
|
||||
Long maxFee = item.getMaxFee();
|
||||
// 借记卡费率上限
|
||||
parameter.put("cuDebitMaxFee", BigDecimal.valueOf(maxFee).divide(bigDecimal100, 2, RoundingMode.DOWN).stripTrailingZeros().toPlainString());
|
||||
if (PaywayFee.FEE_TYPE_LEVEL.equals(feeType)) {
|
||||
// 分级
|
||||
item.getLevelList().forEach(levelItem -> {
|
||||
if (Objects.equals(levelItem.getMinFee(), 100000L)) {
|
||||
// 银联借记卡大额费率
|
||||
BigDecimal feeRate = levelItem.getFeeRate();
|
||||
parameter.put("cuRateDebit", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
|
||||
}
|
||||
});
|
||||
// 贷记卡, 不支持小微
|
||||
item.getCreditCardPaywayFee().getLevelList().forEach(levelItem -> {
|
||||
BigDecimal feeRate = levelItem.getFeeRate();
|
||||
if (Objects.equals(levelItem.getMinFee(), 100000L)) {
|
||||
// 银联贷记卡大额费率
|
||||
parameter.put("cuRateCredit", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
|
||||
} else {
|
||||
// 银联贷记卡小额费率
|
||||
parameter.put("smallDiscountRate", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 线上费率
|
||||
if (item.getWayCode().equals(CS.PAY_WAY_CODE.SCAN)) {
|
||||
BigDecimal feeRate = item.getFeeRate();
|
||||
parameter.put("zhifubaoRate", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
|
||||
parameter.put("weixinRate", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
|
||||
|
||||
// 银联借记卡大额费率
|
||||
parameter.put("cuRateDebit", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
|
||||
// 小额优惠费率
|
||||
parameter.put("smallDiscountRate", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
|
||||
//
|
||||
parameter.put("cuRateCredit", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
|
||||
|
||||
parameter.put("cuDebitMaxFee", "20.0");
|
||||
}
|
||||
});
|
||||
|
||||
// 轻快付
|
||||
parameter.put("terminalQkf", "1");
|
||||
parameter.put("isWechatAppletPay", "1");
|
||||
|
||||
String paySiteUrl = sysConfigService.getDBApplicationConfig().getPaySiteUrl();
|
||||
;
|
||||
if (paySiteUrl == null || paySiteUrl.isEmpty()) {
|
||||
throw new BizException("未获取到支付网关信息");
|
||||
}
|
||||
|
||||
// 微信配置
|
||||
WxpayOauth2Params wxpayOauth2Params = (WxpayOauth2Params) configContextQueryService.queryIsvOauth2Params(mchApplyment.getIsvNo(), CS.IF_CODE.WXPAY);
|
||||
if (wxpayOauth2Params == null) {
|
||||
throw new BizException("服务商未配置微信oauth信息");
|
||||
}
|
||||
|
||||
parameter.put("wechatAppID", "wxc81c4ae33fe525f0");
|
||||
parameter.put("wechatMchID", "1502807381");
|
||||
parameter.put("wechatChannelID", "191695524");
|
||||
|
||||
String liteAppId = wxpayOauth2Params.getLiteAppId();
|
||||
if (ObjectUtils.isEmpty(liteAppId)) {
|
||||
parameter.put("wechatSubAppId", wxpayOauth2Params.getAppId());
|
||||
} else {
|
||||
parameter.put("wechatSubAppId", wxpayOauth2Params.getAppId() + ";" + wxpayOauth2Params.getLiteAppId());
|
||||
}
|
||||
parameter.put("wechatJsapi", paySiteUrl + "/");
|
||||
|
||||
// 支付宝配置
|
||||
AlipayOauth2Params alipayOauth2Params = (AlipayOauth2Params) configContextQueryService.queryIsvOauth2Params(mchApplyment.getIsvNo(), CS.IF_CODE.ALIPAY);
|
||||
if (alipayOauth2Params == null) {
|
||||
throw new BizException("服务商未配置微信oauth信息");
|
||||
}
|
||||
|
||||
parameter.put("isAlipayAppletPay", "1");
|
||||
parameter.put("aliAppID", "1266000048120000");
|
||||
parameter.put("aliSource", "2088821475893827");
|
||||
parameter.put("aliPid", "2088821475893827");
|
||||
|
||||
return packInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.jeequan.jeepay.core.entity.MchApplyment rejectModify(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
|
||||
return firstApplyment(mchApplyment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.jeequan.jeepay.core.entity.MchApplyment replenishInfo(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.jeequan.jeepay.core.entity.MchApplyment query(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
|
||||
log.info("快钱商户入网状态查询, 商户号为{}", mchApplyment.getApplyId());
|
||||
com.jeequan.jeepay.core.entity.MchApplyment result = new com.jeequan.jeepay.core.entity.MchApplyment();
|
||||
result.setApplyId(mchApplyment.getApplyId());
|
||||
result.setState(mchApplyment.getState());
|
||||
JSONObject bizJSON = new JSONObject();
|
||||
String orderId = mchApplyment.getChannelApplyNo();
|
||||
bizJSON.put("orderId", orderId);
|
||||
|
||||
KqpayIsvParams isvParams = (KqpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);
|
||||
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(mchApplyment);
|
||||
KqpayResp kqpayResp = KqpayKit.applymentRequest(KqpayConst.ReqMethod.BS002, isvParams, bizJSON);
|
||||
JSONObject responseBody = kqpayResp.getResponseBody();
|
||||
String bizResponseCode = responseBody.getString("bizResponseCode");
|
||||
String bizResponseMessage = responseBody.getString("bizResponseMessage");
|
||||
if (!KqpayConst.SUCCESS.equals(bizResponseCode)) {
|
||||
log.info("快钱查询商户审核状态失败, {}", bizResponseMessage);
|
||||
return mchApplyment;
|
||||
}
|
||||
|
||||
String status = responseBody.getString("status");
|
||||
String comments = responseBody.getString("comments");
|
||||
JSONObject openResult = responseBody.getJSONObject("openResult");
|
||||
|
||||
if ("AUDITING".equals(status)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.setApplyErrorInfo(comments);
|
||||
if ("TO_BE_SIGNED".equals(status)) {
|
||||
|
||||
int allowSign = isAllowSign(mchApplyment);
|
||||
// 待签约
|
||||
if (allowSign == 1) {
|
||||
// 可以签约的话,直接签约之后再查询
|
||||
signApply(mchApplyment);
|
||||
|
||||
return query(mchApplyment);
|
||||
}
|
||||
|
||||
// 待激活
|
||||
if (allowSign == 2) {
|
||||
result.setState(MchApplyment.STATE_WAIT_SIGN);
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if ("TO_BE_REAUDITED".equals(status)) {
|
||||
if (openResult != null) {
|
||||
result.setChannelMchNo(openResult.getString("subMerchantId"));
|
||||
result.setSuccResParameter(openResult.toString());
|
||||
subMchColl(mchApplyment, openResult);
|
||||
}
|
||||
result.setState(MchApplyment.STATE_SUCCESS_NEED_SECOND_VERIFY);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if ("REJECTED".equals(status)) {
|
||||
result.setState(com.jeequan.jeepay.core.entity.MchApplyment.STATE_REJECT_WAIT_MODIFY);
|
||||
return result;
|
||||
}
|
||||
|
||||
if ("FINISHED".equals(status)) {
|
||||
if (openResult != null) {
|
||||
result.setChannelMchNo(openResult.getString("subMerchantId"));
|
||||
result.setSuccResParameter(openResult.toString());
|
||||
subMchColl(mchApplyment, openResult);
|
||||
}
|
||||
result.setState(com.jeequan.jeepay.core.entity.MchApplyment.STATE_SUCCESS);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplymentSignInfo signInfo(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.jeequan.jeepay.core.entity.MchApplyment signApply(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
|
||||
String orderId = mchApplyment.getChannelVar1();
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("orderId", mchApplyment.getChannelApplyNo());
|
||||
|
||||
KqpayIsvParams isvParams = (KqpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);
|
||||
|
||||
KqpayResp kqpayResp = KqpayKit.applymentRequest(KqpayConst.ReqMethod.BS004, isvParams, param);
|
||||
JSONObject responseBody = kqpayResp.getResponseBody();
|
||||
String bizResponseCode = responseBody.getString("bizResponseCode");
|
||||
String bizResponseMessage = responseBody.getString("bizResponseMessage");
|
||||
|
||||
if (!KqpayConst.SUCCESS.equals(bizResponseCode)) {
|
||||
log.info("发起签约失败, {}", bizResponseMessage);
|
||||
throw new BizException(bizResponseMessage);
|
||||
}
|
||||
|
||||
String authStatus = responseBody.getString("authStatus");
|
||||
if (!"1".equals(authStatus)) {
|
||||
throw new BizException("签约失败");
|
||||
} else {
|
||||
mchApplyment.setState(com.jeequan.jeepay.core.entity.MchApplyment.STATE_FINISH_SIGN);
|
||||
}
|
||||
|
||||
return mchApplyment;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mchApplyment
|
||||
* @return 返回1,可以使用接口签约,2,需要快钱官网手动签约
|
||||
*/
|
||||
public int isAllowSign(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
|
||||
String orderId = mchApplyment.getChannelApplyNo();
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("orderId", orderId);
|
||||
|
||||
MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
|
||||
mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
|
||||
mchAppConfigContext.setMchApplyment(mchApplyment);
|
||||
|
||||
KqpayIsvParams isvParams = (KqpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);
|
||||
|
||||
KqpayResp kqpayResp = KqpayKit.applymentRequest(KqpayConst.ReqMethod.BS003, isvParams, param);
|
||||
JSONObject responseBody = kqpayResp.getResponseBody();
|
||||
String bizResponseCode = responseBody.getString("bizResponseCode");
|
||||
String bizResponseMessage = responseBody.getString("bizResponseMessage");
|
||||
|
||||
if (!KqpayConst.SUCCESS.equals(bizResponseCode)) {
|
||||
//
|
||||
log.info("查询签约状态失败, {}", bizResponseMessage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
JSONArray econtractList = responseBody.getJSONArray("econtractList");
|
||||
for (int i = 0; i < econtractList.size(); i++) {
|
||||
JSONObject econtract = econtractList.getJSONObject(i);
|
||||
|
||||
/*
|
||||
* 0:待签约;
|
||||
* 1:签约成功;
|
||||
* 2:签约拒绝;
|
||||
* 3:快钱账户待激活;
|
||||
* 4:合同生成,待转 PDF;
|
||||
* 6:签约中;
|
||||
* 7:签约失败;
|
||||
* -1:未生成合同
|
||||
*/
|
||||
if (econtract.getString("authStatus").equals("0")) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (econtract.getString("authStatus").equals("3")) {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subMchColl(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment, Object openResult1) {
|
||||
JSONObject openResult = (JSONObject) openResult1;
|
||||
|
||||
String subMerchantId = openResult.getString("subMerchantId");
|
||||
List<MchSubInfoEntity> mchSubInfoEntityList = new ArrayList<>();
|
||||
|
||||
JSONArray alipayList = openResult.getJSONArray("alipayList");
|
||||
if (!CollUtil.isEmpty(alipayList)) {
|
||||
getByOpenResultItem(mchApplyment.getApplyId(), subMerchantId, "ZFB", alipayList);
|
||||
}
|
||||
|
||||
JSONArray wechatList = openResult.getJSONArray("wechatList");
|
||||
if (!CollUtil.isEmpty(wechatList)) {
|
||||
getByOpenResultItem(mchApplyment.getApplyId(), subMerchantId, "WX", wechatList);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void getByOpenResultItem(String mchApplyId, String channelMchNo, String subChannelType, JSONArray subMchArr) {
|
||||
List<MchSubInfoEntity> mchSubInfoEntityList = new ArrayList<>();
|
||||
for (int i = 0; i < subMchArr.size(); i++) {
|
||||
JSONObject openResultItem = subMchArr.getJSONObject(i);
|
||||
MchSubInfoEntity entity = new MchSubInfoEntity();
|
||||
entity.setChannelMchNo(channelMchNo);
|
||||
entity.setRemark(openResultItem.getString("errorMsg"));
|
||||
entity.setSubMchId(openResultItem.getString("subMchId"));
|
||||
entity.setStatus(openResultItem.getString("status"));
|
||||
entity.setSubMchType(subChannelType);
|
||||
entity.setSubMchWay("KQ");
|
||||
entity.setMchApplyId(mchApplyId);
|
||||
entity.setMainUse(1);
|
||||
entity.setAuthStatus(MchSubInfo.AUTH_STATUS_UNKNOWN);
|
||||
|
||||
try {
|
||||
mchSubInfoService.saveBatch(mchSubInfoEntityList);
|
||||
} catch (DuplicateKeyException e) {
|
||||
log.info("快钱子商户信息已存在");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void subMchColl(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
|
||||
query(mchApplyment);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.jeequan.jeepay.thirdparty.channel.kqpay;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.jeequan.jeepay.core.entity.PayOrder;
|
||||
import com.jeequan.jeepay.core.interfaces.paychannel.IPayOrderQueryService;
|
||||
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
|
||||
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.model.KqpayOrderStatus;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.model.KqpayResp;
|
||||
import com.jeequan.jeepay.thirdparty.channel.kqpay.util.KqpayConst;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 查询订单 快钱支付
|
||||
*
|
||||
* @author xiaoyu
|
||||
*
|
||||
* @date 2022/4/15 14:29
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class KqpayPayOrderQueryService implements IPayOrderQueryService {
|
||||
|
||||
@Override
|
||||
public ChannelRetMsg query(PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
|
||||
JSONObject bizContent = new JSONObject();
|
||||
KqpayKit.setPayParams(mchAppConfigContext,bizContent);
|
||||
bizContent.put("idOrderCtrl",payOrder.getChannelOrderNo());
|
||||
KqpayResp resp = KqpayKit.payRequest(KqpayConst.ReqMethod.A7006,mchAppConfigContext,bizContent,payOrder.getPayOrderId());
|
||||
JSONObject responseBody = resp.getResponseBody();
|
||||
KqpayOrderStatus txnStatus = KqpayOrderStatus.getVal(responseBody.getString("txnStatus"));
|
||||
String transNo = responseBody.getString("idOrderCtrl");
|
||||
String channelTradeNo = responseBody.getString("channelTradeNo");
|
||||
String channelSendSn = responseBody.getString("idTxnCtrl");
|
||||
String bizResponseCode = responseBody.getString("bizResponseCode");
|
||||
String bizResponseMessage = responseBody.getString("bizResponseMessage");
|
||||
ChannelRetMsg retMsg = ChannelRetMsg.confirmSuccess(transNo, channelTradeNo, channelSendSn,null);
|
||||
retMsg.setChannelUserId(responseBody.getString("thirdPartyBuyerId"));
|
||||
switch (txnStatus){
|
||||
case PROCESS:
|
||||
return ChannelRetMsg.waiting();
|
||||
case FAIL:
|
||||
return ChannelRetMsg.confirmFail(bizResponseCode,bizResponseMessage);
|
||||
case CORRECT:
|
||||
return ChannelRetMsg.waiting();
|
||||
default:
|
||||
return retMsg;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user