ghy-all/ghy-payment/src/main/java/com/ghy/payment/service/AdapayService.java

562 lines
30 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.ghy.payment.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ghy.common.adapay.AdapayConfig;
import com.ghy.common.adapay.AdapayProperties;
import com.ghy.common.adapay.model.*;
import com.ghy.common.enums.RefundType;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import com.huifu.adapay.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import javax.validation.constraints.NotNull;
import java.util.Collection;
import java.util.List;
/**
* @author HH 2022/3/25
*/
@Slf4j
@Service
public class AdapayService {
private ThreadPoolTaskExecutor executor;
private AdapayProperties adapayProperties;
private CallBackService payCallbackService;
private CallBackService refundCallbackService;
private CallBackService drawCashCallbackService;
private CallBackService payReverseCallbackService;
@Autowired
public void setExecutor(ThreadPoolTaskExecutor threadPoolTaskExecutor) {
this.executor = threadPoolTaskExecutor;
}
@Autowired
public void setAdapayProperties(AdapayProperties adapayProperties) {
log.info("Adapay load properties: {}", JSON.toJSONString(adapayProperties));
this.adapayProperties = adapayProperties;
}
@Autowired
public void setPayCallbackService(CallBackService payCallbackService) {
log.info("Adapay load callback: {}", payCallbackService.getClass().toString());
this.payCallbackService = payCallbackService;
}
@Autowired
public void setRefundCallbackService(CallBackService refundCallbackService) {
log.info("Adapay load callback: {}", refundCallbackService.getClass().toString());
this.refundCallbackService = refundCallbackService;
}
@Autowired
public void setDrawCashCallbackService(CallBackService drawCashCallbackService) {
log.info("Adapay load callback: {}", drawCashCallbackService.getClass().toString());
this.drawCashCallbackService = drawCashCallbackService;
}
@Autowired
public void setPayReverseCallbackService(CallBackService payReverseCallbackService) {
log.info("Adapay load callback: {}", payReverseCallbackService.getClass().toString());
this.payReverseCallbackService = payReverseCallbackService;
}
/**
* 查询支付对象
*
* @param deptId [必填]商户ID
* @param paymentId [必填] String(64) Adapay生成的支付对象id
* @return 支付对象
*/
public JSONObject getPayment(@NotNull Long deptId, @NotNull String paymentId) {
try {
return (JSONObject) Payment.query(paymentId, deptId.toString());
} catch (BaseAdaPayException e) {
e.printStackTrace();
}
return null;
}
/**
* 支付确认
* 适用于延时分账的场景。只有已支付完成且延时分账的Payment对象才支持调用创建支付确认对象。
* 支持一次全额或多次部分确认,多次部分确认时,当前确认金额 + 已确认金额 + 已撤销金额不能大于原支付金额。
*
* @param deptId [必填]商户ID
* @param paymentId [必填] String(64) Adapay生成的支付对象id
* @param orderNo [必填] String(64) 请求订单号只能为英文、数字或者下划线的一种或多种组合保证在app_id下唯一
* @param confirmAmt [必填] String(14) 确认金额必须大于0保留两位小数点如0.10、100.05等。必须小于等于原支付金额-已确认金额-已撤销金额
* @param divMembers 分账对象信息列表一次请求最多仅支持7个分账方。json对象 形式,详见 分账对象信息列表
* @param feeMode String(1) 手续费收取模式O-商户手续费账户扣取手续费I-交易金额中扣取手续费值为空时默认值为I若为O时分账对象列表中不支持传入手续费承担方
* @param description String(128) 附加说明
* @return 成功时同步返回一个包含 支付确认对象的JSON https://docs.adapay.tech/api/trade.html#id54
* 成功示例:{
* "order_no": "TEST18888888888_001",
* "created_time": "1670932918",
* "confirm_amt": "10.00",
* "confirmed_amt": "0.00",
* "reserved_amt": "0.00",
* "div_members": [{
* "member_id": "W7D888",
* "amount": "10.00",
* "fee_flag": "Y"
* }],
* "refunded_amt": "0.00",
* "prod_mode": "true",
* "id": "0021120221213200158990448709336858888888",
* "app_id": "app_01af32e7-6173-414f-88e5-79cae64d5e24",
* "fee_amt": "0.08",
* "object": "payment_confirm",
* "status": "succeeded"
* }
*/
public JSONObject paymentConfirm(@NotNull Long deptId, @NotNull String paymentId, @NotNull String orderNo,
@NotNull String confirmAmt, List<DivMember> divMembers,
String feeMode, String description) throws BaseAdaPayException {
JSONObject confirmParams = new JSONObject();
confirmParams.put("payment_id", paymentId);
confirmParams.put("order_no", orderNo);
confirmParams.put("confirm_amt", confirmAmt);
confirmParams.put("div_members", divMembers);
confirmParams.put("fee_mode", feeMode);
confirmParams.put("description", description);
log.info("发起支付确认 dept[{}] param:{}", deptId, confirmParams.toJSONString());
JSONObject response = (JSONObject) PaymentConfirm.create(confirmParams, deptId.toString());
log.info("支付确认结果 dept[{}] response:{}", deptId, response.toJSONString());
return response;
}
/**
* 创建余额支付请求
* 商户利用该接口进行余额支付,支持同一商户下的商户-用户,用户-商户,用户-用户间的账户余额支付
*
* @param deptId [必填]商户ID
* @param orderNo [必填]请求订单号只能为英文、数字或者下划线的一种或多种组合保证在app_id下唯一
* @param outMemberId [必填]出账用户的member_id 若为商户本身时请传入0
* @param inMemberId [必填]入账用户的member_id 若为商户本身时请传入0
* @param transAmt [必填]交易金额必须大于0人民币为元保留两位小数点如"0.10"、"100.05"等
* @param goodsTitle [必填]商品名称
* @param goodsDesc [必填]商品描述
* @param payMode 支付模式delay- 延时分账模式(值为 delay 时div_members 字段必须为空);
* 值为空时并且div_mermbers不为空时表示实时分账
* 值为空时并且div_mermbers也为空时表示不分账
* @param divMembers 分账对象信息列表最多仅支持7个分账方
* @return 成功时同步返回交易结果的 JSON
*/
public JSONObject balancePay(@NotNull Long deptId, @NotNull String orderNo, @NotNull String outMemberId,
@NotNull String inMemberId, @NotNull String transAmt, @NotNull String goodsTitle,
@NotNull String goodsDesc, String payMode, Collection<DivMember> divMembers) throws BaseAdaPayException {
// 获取商户的appId
String appId = AdapayConfig.getAppId(deptId);
JSONObject balanceParam = new JSONObject();
balanceParam.put("app_id", appId);
balanceParam.put("adapay_func_code", "settle_accounts.balancePay");
balanceParam.put("order_no", orderNo);
balanceParam.put("out_member_id", outMemberId);
balanceParam.put("in_member_id", inMemberId);
balanceParam.put("trans_amt", transAmt);
balanceParam.put("goods_title", goodsTitle);
balanceParam.put("goods_desc", goodsDesc);
balanceParam.put("pay_mode", payMode);
if (!CollectionUtils.isEmpty(divMembers)) {
balanceParam.put("div_members", divMembers);
}
return (JSONObject) AdapayCommon.requestAdapay(balanceParam, deptId.toString());
}
/**
* 创建结算账户对象 https://docs.adapay.tech/api/trade.html#settle-account-create
* 创建结算账户对象是为一个已创建用户对象创建结算账户,用于对用户分账金额的结算,目前仅支持绑定银行卡结算账户。
* 用户创建对私结算账户时,会对银行卡号、银行卡开户姓名、身份证号三要素认证,若认证失败,则创建结算账户失败。
* 每个结算账户对象 Adapay 系统会生成一个唯一的 id可用于查询结算账户对象或者删除结算账户对象。
*
* @param deptId [必填]商户ID
* @param memberId [必填]商户下的用户id只能为英文、数字或者下划线的一种或多种组合保证在app_id下唯一
* @param cardId [必填]银行卡号
* @param cardName [必填]银行卡对应的户名
* @param telNo [必填]手机号
* @param bankAcctType [必填]银行账户类型1-对公2-对私
* @param certId 证件号,银行账户类型为对私时必填
* @param bankCode 银行编码,银行账户类型对公时必填,详见附录 银行代码 https://docs.adapay.tech/api/appendix.html#id3
* @param provCode 银行账户开户银行所在省份编码 省市编码银行账户类型为对公时必填省市编码详见area.json
* @param areaCode 银行账户开户银行所在地区编码省市编码银行账户类型为对公时必填省市编码详见area.json
* @return 成功时同步返回一个包含 SettleAccount对象 的 JSON。
*/
public JSONObject createSettleAccount(@NotNull Long deptId, @NotNull String memberId, @NotNull String cardId,
@NotNull String cardName, @NotNull String bankAcctType, String certId, String telNo,
String bankCode, String provCode, String areaCode) throws BaseAdaPayException {
// 获取商户的appId
String appId = AdapayConfig.getAppId(deptId);
// 结算账户信息 参见结算账户信息(AccountInfo)对象 https://docs.adapay.tech/api/appendix.html#accountinfo
JSONObject accountInfo = new JSONObject();
switch (bankAcctType) {
case "1":
Assert.isTrue(StringUtils.isNoneBlank(bankCode, provCode, areaCode),
"[bankCode, provCode, areaCode] cannot be empty !");
break;
case "2":
Assert.hasText(cardId, "cardId is blank !");
accountInfo.put("cert_type", "00");
accountInfo.put("cert_id", certId);
break;
default:
throw new BaseAdaPayException("Wrong bankAcctType !");
}
accountInfo.put("card_id", cardId);
accountInfo.put("card_name", cardName);
accountInfo.put("tel_no", telNo);
accountInfo.put("bank_code", bankCode);
accountInfo.put("bank_acct_type", bankAcctType);
accountInfo.put("prov_code", provCode);
accountInfo.put("area_code", areaCode);
JSONObject settleCountParams = new JSONObject();
settleCountParams.put("member_id", memberId);
settleCountParams.put("app_id", appId);
// 目前仅支持bank_account银行卡
settleCountParams.put("channel", "bank_account");
settleCountParams.put("account_info", accountInfo);
return (JSONObject) SettleAccount.create(settleCountParams, deptId.toString());
}
/**
* 查询商户或商户下某个用户结算账户的余额
*
* @param deptId [必填]商户ID
* @param memberId [必填]商户用户对象 id只能为英文、数字或者下划线的一种或多种组合若查询商户本身时传入值0
* @param settleAccountId 由Adapay生成的结算账户对象id若查询商户本身时可为空而当查询商户下的用户时必填
* @param acctType 账户类型01或者为空是基本户02是手续费账户03是过渡户
* @return https://docs.adapay.tech/api/wallet.html#id13
* 成功示例: {"acct_balance": "0.00",
* "app_id": "app_XXXXXXXX",
* "avl_balance": "0.00",
* "frz_balance": "0.00",
* "last_avl_balance": "0.00",
* "object": "account_balance",
* "status": "succeeded",
* "prod_mode": "true"}
*/
public JSONObject queryAccountBalance(@NotNull Long deptId, @NotNull String memberId, String settleAccountId, String acctType) throws BaseAdaPayException {
// 获取商户的appId
String appId = AdapayConfig.getAppId(deptId);
JSONObject queryParams = new JSONObject(5);
queryParams.put("settle_account_id", settleAccountId);
queryParams.put("member_id", memberId);
queryParams.put("app_id", appId);
queryParams.put("acct_type", acctType);
return (JSONObject) SettleAccount.balance(queryParams, deptId.toString());
}
/**
* 提现钱包里的所有余额(仅用于商户下的用户)
*
* @param deptId [必填]商户ID
* @param memberId [必填]商户用户对象 id只能为英文、数字或者下划线的一种或多种组合
* @param settleAccountId [必填]由Adapay生成的结算账户对象id
* @return 可用余额不足时 return null;
* 其它同 {@link AdapayService#drawCash(Long, String, String, String, String, String, String)}
*/
public JSONObject drawCashAll(@NotNull Long deptId, @NotNull String memberId, @NotNull String settleAccountId) throws BaseAdaPayException {
JSONObject balance = queryAccountBalance(deptId, memberId, settleAccountId, null);
if (AdapayStatusEnum.succeeded.code.equals(balance.getString("status"))) {
// 可用余额
String avlBalance = balance.getString("avl_balance");
if (StringUtils.isBlank(avlBalance) || "0.00".equals(avlBalance) || avlBalance.startsWith("-")) {
// 可用余额不足
return null;
}
return drawCash(deptId, "", "T1", avlBalance, memberId, "", null);
} else {
throw new BaseAdaPayException(balance.getString("error_code") + ": " + balance.getString("error_msg"));
}
}
/**
* 删除结算账户对象 https://docs.adapay.tech/api/trade.html#id50
* 删除结算账户对象是对已创建完成的结算账户对象进行删除操作。
* 删除结算账户成功后,支付时不再支持分账功能。您可再调用创建结算账户对象创建新的结算账户。
* 删除结算账户对象需要 Adapay 系统生成的结算账户对象 id 进行删除。
*
* @param deptId [必填]商户ID
* @param memberId [必填]商户下的用户id只能为英文、数字或者下划线的一种或多种组合保证在app_id下唯一
* @param settleAccountId [必填]结算账户ID
* @return { "status": "succeeded", "id":"0006440476699456", "prod_mode": "true" }
*/
public JSONObject deleteSettleAccount(@NotNull Long deptId, @NotNull String memberId, @NotNull String settleAccountId) throws BaseAdaPayException {
String appId = AdapayConfig.getAppId(deptId);
JSONObject settleCountParams = new JSONObject();
settleCountParams.put("app_id", appId);
settleCountParams.put("settle_account_id", settleAccountId);
settleCountParams.put("member_id", memberId);
return (JSONObject) SettleAccount.delete(settleCountParams, deptId.toString());
}
/**
* 创建实名用户 https://docs.adapay.tech/api/trade.html#member-realname
*
* @param deptId [必填]商户ID
* @param memberId [必填]商户下的用户id只能为英文、数字或者下划线的一种或多种组合保证在app_id下唯一
* @param telNo [必填]用户手机号
* @param username [必填]用户姓名
* @param certId [必填]证件号
* @return 成功时同步返回一个包含Member对象的JSON
*/
public JSONObject createMember(@NotNull Long deptId, @NotNull String memberId, @NotNull String telNo,
@NotNull String username, @NotNull String certId) throws BaseAdaPayException {
// 获取商户的appId
String appId = AdapayConfig.getAppId(deptId);
JSONObject memberParams = new JSONObject();
memberParams.put("member_id", memberId);
memberParams.put("app_id", appId);
memberParams.put("tel_no", telNo);
memberParams.put("user_name", username);
// 证件类型仅支持00-身份证
memberParams.put("cert_type", "00");
// 接口功能号
memberParams.put("adapay_func_code", "members.realname");
memberParams.put("cert_id", certId);
return (JSONObject) AdapayCommon.requestAdapay(memberParams, deptId.toString());
}
/**
* 对指定商户或者商户下用户的结算账户可用余额发起主动取现操作,金额从账户中提到绑定的结算银行卡中
*
* @param deptId [必填]商户ID
* @param orderNo [必填项]请求订单号只能为英文、数字或者下划线的一种或多种组合保证在app_id下唯一
* @param cashType [必填项]取现类型T1-T+1取现D1-D+1取现D0-即时取现。
* @param cashAmt [必填项]取现金额必须大于0人民币为元保留两位小数点如"0.10"、"100.05"等
* @param memberId [必填项]用户对象的member_id若是商户本身取现时请传入0
* @param remark 备注
* @param feeMode 手续费收取模式O-商户手续费账户扣取手续费I-交易金额中扣取手续费值为空时默认值为I
* @return https://docs.adapay.tech/api/wallet.html#cash-response
*/
public JSONObject drawCash(@NotNull Long deptId, String orderNo, String cashType, String cashAmt,
String memberId, String remark, String feeMode) throws BaseAdaPayException {
// 获取商户的appId
String appId = AdapayConfig.getAppId(deptId);
Assert.hasText(orderNo, "orderNo is blank!");
Assert.hasText(cashType, "cashType is blank!");
Assert.hasText(cashAmt, "cashAmt is blank!");
Assert.hasText(memberId, "memberId is blank!");
JSONObject cashParam = new JSONObject();
cashParam.put("order_no", orderNo);
cashParam.put("app_id", appId);
cashParam.put("cash_type", cashType);
cashParam.put("cash_amt", cashAmt);
cashParam.put("member_id", memberId);
cashParam.put("notify_url", adapayProperties.getNotifyUrl());
cashParam.put("remark", remark);
cashParam.put("fee_mode", feeMode);
log.info("发起提现 dept[{}] param:{}", deptId, cashParam.toJSONString());
JSONObject response = (JSONObject) Drawcash.create(cashParam, deptId.toString());
log.info("提现结果 dept[{}] response:{}", deptId, response.toJSONString());
response.put("dept_id", deptId);
executor.execute(() -> drawCashCallbackService.onResponse(response));
return response;
}
/**
* 通过该功能,可以查询已发起的取现交易状态。
*
* @param deptId [必填]商户ID
* @param orderNo [必填项]请求订单号只能为英文、数字或者下划线的一种或多种组合保证在app_id下唯一
* @return https://docs.adapay.tech/api/wallet.html#query-cash-response
* 失败示例: {"error_msg":"未查到相关取现信息","error_type":"invalid_request_error","prod_mode":"true","error_code":"cash_error","status":"failed"}
* 成功示例: {"cash_list":[{"cash_id":"0021110483925412449046528","trans_stat":"P","cash_amt":"19.87"}],"prod_mode":"true","status":"succeeded"}
*/
public JSONObject queryDrawCash(@NotNull Long deptId, @NotNull String orderNo) throws BaseAdaPayException {
Assert.hasText(orderNo, "orderNo is blank!");
JSONObject queryCashParam = new JSONObject();
queryCashParam.put("order_no", orderNo);
return (JSONObject) Drawcash.query(queryCashParam, deptId.toString());
}
/**
* 支付宝正扫支付
*/
public JSONObject alipayQrPay(@NotNull Long deptId, PayParam payParam,
AlipayExpend expend, DeviceInfo deviceInfo,
Collection<DivMember> divMembers) throws BaseAdaPayException {
return pay(deptId, "alipay_qr", payParam, expend, deviceInfo, divMembers);
}
/**
* 微信公众号支付
*/
public JSONObject wxPubPay(@NotNull Long deptId, PayParam payParam,
WxpayExpend expend, DeviceInfo deviceInfo,
Collection<DivMember> divMembers) throws BaseAdaPayException {
return pay(deptId, "wx_pub", payParam, expend, deviceInfo, divMembers);
}
/**
* 微信小程序支付
*/
public JSONObject wxLitePay(@NotNull Long deptId, PayParam payParam,
WxpayExpend expend, DeviceInfo deviceInfo,
Collection<DivMember> divMembers) throws BaseAdaPayException {
return pay(deptId, "wx_lite", payParam, expend, deviceInfo, divMembers);
}
/**
* 聚合支付
*
* @param deptId [必填]商户ID
* @param payChannel [必填项]支付渠道,详见 https://docs.adapay.tech/api/appendix.html#id2
* @param payParam [必填项]支付参数
* @param expend 支付渠道额外参数 https://docs.adapay.tech/api/appendix.html#expend
* @param deviceInfo 前端设备信息 https://docs.adapay.tech/api/appendix.html#deviceinfo
* @param divMembers 分账对象信息列表 https://docs.adapay.tech/api/appendix.html#divmembers
* @return 同步返回一个 支付对象,详见 https://docs.adapay.tech/api/trade.html#id2
* 成功示例: {
* "order_no": "TEST18888888888_001",
* "created_time": "1670932358",
* "party_order_id": "02212212137155817188888",
* "pay_amt": "10.00",
* "expend": {
* "qrcode_url": "https://qr.alipay.com/bax022139la4gqagxbti8888"
* },
* "prod_mode": "true",
* "pay_channel": "alipay_qr",
* "query_url": "https://api.adapay.tech/v1/expire/payments/1/cff1102a8a0d5d4be1d444acb7726fdd",
* "id": "002112022121319523810448706986096888888",
* "app_id": "app_01af32e7-6173-414f-88e5-79cae64d5e24",
* "object": "payment",
* "status": "succeeded"
* }
*/
public JSONObject pay(@NotNull Long deptId, @NotNull String payChannel, @NotNull PayParam payParam,
Expend expend, DeviceInfo deviceInfo,
Collection<DivMember> divMembers) throws BaseAdaPayException {
// 获取商户的appId
String appId = AdapayConfig.getAppId(deptId);
JSONObject paymentParams = payParam.toJSONObject();
paymentParams.put("app_id", appId);
paymentParams.put("notify_url", adapayProperties.getNotifyUrl());
paymentParams.put("pay_channel", payChannel);
paymentParams.put("div_members", divMembers);
paymentParams.put("device_info", deviceInfo);
paymentParams.put("expend", expend);
log.debug("paymentParams: {}", paymentParams.toJSONString());
JSONObject response = (JSONObject) Payment.create(paymentParams, deptId.toString());
executor.execute(() -> payCallbackService.onResponse(response));
return response;
}
/**
* 发起退款
* 当您的业务需要发起退款时,可通过 Adapay 系统提供的创建 Refund对象 方法创建一个退款对象,资金会原路退回用户的支付宝或微信中。
* 支持一次全额或多次部分退款退款次数最多不超过10次。多次部分退款时当前退款金额 + 已退款金额不能大于原支付金额。
* 对于每次撤销交易Adapay 都会通过 异步消息通知 告知结果。
* 退款对象同步返回成功表示Adapay受理成功退款结果以异步通知为准。支持退款最长时间为178天
* 若返回码是“order_id_not_exists 订单记录不存在”,既超过退款期限,无法退款成功。
*
* @param deptId [必填]商户ID
* @param paymentId [必填项]支付确认对象的id
* @param refundOrderNo [必填项]订单号
* @param refundAmt [必填项]退款金额若退款金额小于原交易金额则认为是部分退款必须大于0保留两位小数点如0.10、100.05等
* @return 同步返回一个 退款对象 https://docs.adapay.tech/api/trade.html#create-refund-params
*/
public JSONObject refund(@NotNull Long deptId, @NotNull String paymentId,
@NotNull String refundOrderNo, @NotNull String refundAmt) throws BaseAdaPayException {
Assert.hasText(paymentId, "paymentId is blank!");
Assert.hasText(refundOrderNo, "refundOrderNo is blank!");
Assert.hasText(refundAmt, "refundAmt is blank!");
JSONObject refundParams = new JSONObject();
refundParams.put("refund_amt", refundAmt);
refundParams.put("refund_order_no", refundOrderNo);
JSONObject response = (JSONObject) Refund.create(paymentId, refundParams, deptId.toString());
executor.execute(() -> refundCallbackService.onResponse(response));
return response;
}
/**
* 支付关单
* 针对已经创建的 支付对象,您可以调用关单接口进行交易的关闭。调用此接口后,该用户订单将不再能支付成功。 对于关单功能的使用有如下规则:
* 1.存在关单记录,不能再次关单
* 2.交易时间 1分钟 内无法关单成功
* 3.正扫交易时间超过 2小时 无法关单成功
* 4.支付宝正扫接口,如果用户没有扫码,订单不能关闭成功(二维码给用户展示,如果用户没有用手机去扫码,那这笔就不能关单; 如果用户扫过了的话(无需支付成功)就可以关单了)—-微信正扫无此条限制
* 5.网银和快捷类交易都不支持关单操作
*
* @param deptId [必填]商户ID
* @param paymentId [必填项]由 Adapay 生成的支付对象 id
* @param reason 关单描述
* @param expend 扩展域
* @return 关单的结果将通过一个 JSON 同步返回 https://docs.adapay.tech/api/trade.html#close-payment-response
*/
public JSONObject close(@NotNull Long deptId, String paymentId, String reason, String expend) throws BaseAdaPayException {
Assert.hasText(paymentId, "paymentId is blank!");
JSONObject paymentParams = new JSONObject();
paymentParams.put("payment_id", paymentId);
paymentParams.put("reason", reason);
paymentParams.put("expend", expend);
return (JSONObject) Payment.close(paymentParams, deptId.toString());
}
/**
* 查询已创建的单个用户对象
* https://docs.adapay.tech/api/trade.html#id41
*
* @param deptId [必填]商户ID
* @param memberId [必填]商户下的用户id只能为英文、数字或者下划线的一种或多种组合保证在app_id下唯一
* @return 成功时同步返回一个包含 Member对象的JSON。
*/
public JSONObject queryMember(@NotNull Long deptId, @NotNull String memberId) throws BaseAdaPayException {
JSONObject memberParams = new JSONObject();
memberParams.put("member_id", memberId);
memberParams.put("app_id", AdapayConfig.getAppId(deptId));
return (JSONObject) Member.query(memberParams, deptId.toString());
}
/**
* 支付撤销
* 支付撤销对象适用于[延时分账]的场景。只有已支付完成且为延时分账的Payment对象在没有创建支付确认对象成功之前可以调用创建支付撤销对象。
* 用来撤销支付,资金会原路退回用户的支付宝或微信中。 支持一次全额或多次部分撤销撤销次数最多不超过10次。
* 多次部分撤销时,当前撤销金额 + 已撤销金额 + 已确认金额不能大于原支付金额。
* 对于每次撤销交易Adapay 都会通过 异步消息通知 告知结果。
* https://docs.adapay.tech/api/trade.html#payment-reverse-object
*
* @param deptId [必填]商户ID
* @param paymentId [必填]Adapay生成的支付对象id
* @param reverseAmt [必填]撤销金额必须大于0保留两位小数点如0.10、100.05等。
* 撤销金额必须小于等于支付金额 - 已确认金额 - 已撤销(撤销成功+撤销中)金额。
* @param type 退款类型 回调时根据它找到对应的财务单
* @return 创建支付撤销对象同步返回成功,表示 Adapay 受理成功,撤销结果以异步通知为准
*/
public JSONObject payReverse(@NotNull Long deptId, @NotNull String paymentId, @NotNull String reverseAmt, @NotNull RefundType type) throws BaseAdaPayException {
JSONObject reverseParams = new JSONObject();
reverseParams.put("app_id", AdapayConfig.getAppId(deptId));
reverseParams.put("payment_id", paymentId);
reverseParams.put("reverse_amt", reverseAmt);
reverseParams.put("notify_url", adapayProperties.getNotifyUrl());
reverseParams.put("order_no", type.code + System.currentTimeMillis());
JSONObject response = (JSONObject) PaymentReverse.create(reverseParams, deptId.toString());
response.put("deptId", deptId);
executor.execute(() -> payReverseCallbackService.onResponse(response));
return response;
}
/**
* 通过 Payment对象 的 id 查询一个已创建的 Payment对象。
* 仅支持查询支付交易发起之后3天内的交易状态3天之后的交易状态请使用 对账单下载 对账,或登陆 控制台 查询。
*
* @param deptId [必填]商户ID
* @param paymentId [必填]Adapay生成的支付对象id
* @return https://docs.adapay.tech/api/trade.html#id17
*/
public JSONObject queryPayment(@NotNull Long deptId, @NotNull String paymentId) throws BaseAdaPayException {
return (JSONObject) Payment.query(paymentId, deptId.toString());
}
}