server_commit
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
package io.v.nutz;
|
package io.v.nutz;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import io.v.nutz.pay.bank.china.BankChinaWxPayService;
|
||||||
|
import io.v.nutz.pay.bank.china.pojo.WxPayOrderQueryResponse;
|
||||||
import io.v.nutz.sys.models.*;
|
import io.v.nutz.sys.models.*;
|
||||||
import io.v.nutz.zhgh.proposal.models.ProposalUndertake;
|
import io.v.nutz.zhgh.proposal.models.ProposalUndertake;
|
||||||
import io.v.nutz.sys.services.SysTaskService;
|
import io.v.nutz.sys.services.SysTaskService;
|
||||||
@@ -72,6 +75,9 @@ public class MainLauncher {
|
|||||||
@Inject
|
@Inject
|
||||||
private Dao dao;
|
private Dao dao;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BankChinaWxPayService bankChinaWxPayService;
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
NbApp nb = new NbApp().setArgs(args).setPrintProcDoc(true);
|
NbApp nb = new NbApp().setArgs(args).setPrintProcDoc(true);
|
||||||
nb.getAppContext().setMainPackage("io.v");
|
nb.getAppContext().setMainPackage("io.v");
|
||||||
@@ -92,6 +98,10 @@ public class MainLauncher {
|
|||||||
init_task();
|
init_task();
|
||||||
init_proposal_undertake();
|
init_proposal_undertake();
|
||||||
ioc.get(Globals.class);
|
ioc.get(Globals.class);
|
||||||
|
WxPayOrderQueryResponse queryResponse = bankChinaWxPayService.queryOrder("688695202608281105286524495205");
|
||||||
|
log.info("中国银行交易查询结果:"+JSONUtil.toJsonStr(queryResponse));
|
||||||
|
//bankChinaWxPayService.refundOrder("688695202608281105286524495205", 0.01, "127.0.0.1");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import cn.hutool.core.date.DateUtil;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import io.v.nutz.pay.bank.china.pojo.RefundOrderResponse;
|
||||||
import io.v.nutz.pay.bank.china.pojo.WxAppPayRequestParams;
|
import io.v.nutz.pay.bank.china.pojo.WxAppPayRequestParams;
|
||||||
import io.v.nutz.pay.bank.china.pojo.WxAppPayResponse;
|
import io.v.nutz.pay.bank.china.pojo.WxAppPayResponse;
|
||||||
import io.v.nutz.pay.bank.china.pojo.WxPayOrderQueryResponse;
|
import io.v.nutz.pay.bank.china.pojo.WxPayOrderQueryResponse;
|
||||||
@@ -13,6 +14,7 @@ import io.v.nutz.pay.bank.china.sign.BankPaySign;
|
|||||||
import io.v.nutz.pay.cache.ChinaBankOrderWaitPayCacheService;
|
import io.v.nutz.pay.cache.ChinaBankOrderWaitPayCacheService;
|
||||||
import io.v.nutz.pay.common.CommonConstants;
|
import io.v.nutz.pay.common.CommonConstants;
|
||||||
import io.v.nutz.pay.enums.*;
|
import io.v.nutz.pay.enums.*;
|
||||||
|
import io.v.nutz.pay.util.BillNoUtil;
|
||||||
import io.v.nutz.pay.util.XmlUtil;
|
import io.v.nutz.pay.util.XmlUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
@@ -49,6 +51,9 @@ public class BankChinaWxPayService {
|
|||||||
// 支付交易查询地址
|
// 支付交易查询地址
|
||||||
private static final String APP_ORDER_QUERY_URL = "/PGWPortal/QueryOrderTrans.do";
|
private static final String APP_ORDER_QUERY_URL = "/PGWPortal/QueryOrderTrans.do";
|
||||||
|
|
||||||
|
// 退款请求地址
|
||||||
|
private static final String REFUND_ORDER_URL = "/PGWPortal/RefundOrder.do";
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ChinaBankOrderWaitPayCacheService chinaBankOrderWaitPayCacheService;
|
private ChinaBankOrderWaitPayCacheService chinaBankOrderWaitPayCacheService;
|
||||||
|
|
||||||
@@ -369,4 +374,123 @@ public class BankChinaWxPayService {
|
|||||||
.setUnionPaySeq(unionPaySeq)
|
.setUnionPaySeq(unionPaySeq)
|
||||||
.setQrOvertimeFlag(qrOvertimeFlag);
|
.setQrOvertimeFlag(qrOvertimeFlag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单退款
|
||||||
|
*
|
||||||
|
* @param orderNo 原支付订单的商户订单号
|
||||||
|
* @param refundAmount 退款金额(元),格式:整数位前不补零,小数位补齐2位小数,不超过10位整数+1位小数点+2位小数
|
||||||
|
* @param custIp 客户IP地址(选填)
|
||||||
|
* @return RefundOrderResponse
|
||||||
|
*/
|
||||||
|
public RefundOrderResponse refundOrder(String orderNo, Double refundAmount, String custIp) {
|
||||||
|
payProperties.load();
|
||||||
|
this.checkConfigPayProperties();
|
||||||
|
|
||||||
|
// 商户退款交易流水号:商户号(merchantNo)后6位+商户按自己规则生成的退款交易流水号
|
||||||
|
String mRefundSeq = payProperties.getMerchantNoAfterChar(6).concat(BillNoUtil.getTimeNo(24));
|
||||||
|
// 退款币种固定 001(人民币)
|
||||||
|
String curCode = "001";
|
||||||
|
// 退款金额格式化为2位小数
|
||||||
|
String refundAmountStr = String.format("%.2f", refundAmount);
|
||||||
|
|
||||||
|
// 签名串:商户号|商户退款交易流水号|退款币种|退款金额|商户订单号
|
||||||
|
// 注意:与支付接口签名串保持一致,末尾不添加分隔符
|
||||||
|
String businessSignData = payProperties.getMerchantNo() + "|"
|
||||||
|
+ mRefundSeq + "|"
|
||||||
|
+ curCode + "|"
|
||||||
|
+ refundAmountStr + "|"
|
||||||
|
+ orderNo;
|
||||||
|
log.info("中国银行退款签名原串:businessSignData={}", businessSignData);
|
||||||
|
String signData = BankPaySign.getInstance().getSinData(
|
||||||
|
payProperties.getSignKeyFile(),
|
||||||
|
payProperties.getSignkeyPassword(),
|
||||||
|
payProperties.getSignkeyPassword(),
|
||||||
|
businessSignData);
|
||||||
|
log.info("中国银行退款签名结果:signData={}", signData);
|
||||||
|
|
||||||
|
List<NameValuePair> formParams = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
formParams.add(new BasicNameValuePair("merchantNo", payProperties.getMerchantNo()));
|
||||||
|
formParams.add(new BasicNameValuePair("mRefundSeq", mRefundSeq));
|
||||||
|
formParams.add(new BasicNameValuePair("curCode", curCode));
|
||||||
|
formParams.add(new BasicNameValuePair("refundAmount", refundAmountStr));
|
||||||
|
formParams.add(new BasicNameValuePair("orderNo", orderNo));
|
||||||
|
formParams.add(new BasicNameValuePair("signData", signData));
|
||||||
|
if (StrUtil.isNotBlank(custIp)) {
|
||||||
|
formParams.add(new BasicNameValuePair("custIp", custIp));
|
||||||
|
}
|
||||||
|
log.info("中国银行退款发送参数:{}", JSONObject.toJSONString(formParams));
|
||||||
|
|
||||||
|
try {
|
||||||
|
HttpClient httpClient = new DefaultHttpClient();
|
||||||
|
HttpEntity entity = new UrlEncodedFormEntity(formParams, "UTF-8");
|
||||||
|
String action = payProperties.getDomain() + REFUND_ORDER_URL;
|
||||||
|
log.info("中国银行退款请求地址:{}", action);
|
||||||
|
HttpPost post = new HttpPost(action);
|
||||||
|
post.setEntity(entity);
|
||||||
|
HttpResponse postRes = httpClient.execute(post);
|
||||||
|
HttpEntity entityResult = postRes.getEntity();
|
||||||
|
String result = EntityUtils.toString(entityResult);
|
||||||
|
log.info("---------- BankChinaWxPayService.refundOrder receive message ----------");
|
||||||
|
log.info("[result]=[" + result + "]");
|
||||||
|
if (StrUtil.isBlank(result)) {
|
||||||
|
throw new RuntimeException("BankChinaWxPayService.refundOrder receive message result is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
Document resultDocument = XmlUtil.createDocument(result);
|
||||||
|
// 退款接口响应字段:dealStatus(处理状态1成功/其他失败), bodyFlag(有无业务体0有/1无),
|
||||||
|
// exception(异常码), returnActFlag(操作类型3退款)
|
||||||
|
String dealStatus = XmlUtil.getNodeText(resultDocument, "dealStatus");
|
||||||
|
String bodyFlag = XmlUtil.getNodeText(resultDocument, "bodyFlag", "");
|
||||||
|
String exception = XmlUtil.getNodeText(resultDocument, "exception", "");
|
||||||
|
String returnActFlag = XmlUtil.getNodeText(resultDocument, "returnActFlag", "");
|
||||||
|
log.info("中国银行退款响应头:dealStatus={}, bodyFlag={}, exception={}, returnActFlag={}",
|
||||||
|
dealStatus, bodyFlag, exception, returnActFlag);
|
||||||
|
|
||||||
|
// 处理状态判断:dealStatus = "1" 视为请求级成功;非1或存在异常码时抛出
|
||||||
|
if (StrUtil.isBlank(dealStatus) || !"1".equals(dealStatus)) {
|
||||||
|
String msg = "中国银行退款请求失败: dealStatus=" + dealStatus;
|
||||||
|
if (StrUtil.isNotBlank(exception)) {
|
||||||
|
msg = msg + ", exception=" + exception;
|
||||||
|
}
|
||||||
|
throw new RuntimeException(msg);
|
||||||
|
}
|
||||||
|
// bodyFlag=1 无业务体 + 存在异常码:仍然视为业务失败
|
||||||
|
if ("1".equals(bodyFlag) && StrUtil.isNotBlank(exception)) {
|
||||||
|
throw new RuntimeException("中国银行退款业务失败, exception=" + exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
RefundOrderResponse response = new RefundOrderResponse();
|
||||||
|
response.setHdlSts(dealStatus);
|
||||||
|
response.setRtnMsg(exception);
|
||||||
|
response.setBdFlg(bodyFlag);
|
||||||
|
|
||||||
|
// bodyFlag=0 才有业务体节点可解析
|
||||||
|
if ("0".equals(bodyFlag)) {
|
||||||
|
response = analysisRefundOrderResponseBodyXml(resultDocument);
|
||||||
|
response.setHdlSts(dealStatus);
|
||||||
|
response.setRtnMsg(exception);
|
||||||
|
response.setBdFlg(bodyFlag);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
log.error("中国银行退款请求发起失败:{}", e.getMessage());
|
||||||
|
throw new RuntimeException("中国银行退款请求发起失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private RefundOrderResponse analysisRefundOrderResponseBodyXml(Document document) throws Exception {
|
||||||
|
RefundOrderResponse resp = new RefundOrderResponse();
|
||||||
|
resp.setMerchantNo(XmlUtil.getNodeText(document, "merchantNo"));
|
||||||
|
resp.setOrderNo(XmlUtil.getNodeText(document, "orderNo"));
|
||||||
|
resp.setMRefundSeq(XmlUtil.getNodeText(document, "mRefundSeq"));
|
||||||
|
resp.setOrderStatus(XmlUtil.getNodeText(document, "orderStatus"));
|
||||||
|
resp.setRefundAmount(XmlUtil.getNodeText(document, "refundAmount"));
|
||||||
|
resp.setOrderSeq(XmlUtil.getNodeText(document, "orderSeq"));
|
||||||
|
resp.setBankTranSeq(XmlUtil.getNodeText(document, "bankTranSeq"));
|
||||||
|
resp.setUnionPaySeq(XmlUtil.getNodeText(document, "unionPaySeq"));
|
||||||
|
resp.setSignData(XmlUtil.getNodeText(document, "signData"));
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package io.v.nutz.pay.bank.china.module;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.nutz.dao.entity.annotation.*;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 中国银行支付通知记录
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Comment("中国银行支付通知记录")
|
||||||
|
@Table(value = "china_bank_pay_notify_record")
|
||||||
|
public class ChinaBankPayNotifyRecord implements Serializable {
|
||||||
|
|
||||||
|
@Comment("主键ID")
|
||||||
|
@Column(value = "id")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
@Prev(els = {@EL("uuid()")})
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Comment("商户号")
|
||||||
|
@Column(value = "merchant_no")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||||
|
private String merchantNo;
|
||||||
|
|
||||||
|
@Comment("商户订单号")
|
||||||
|
@Column(value = "order_no")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 64)
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
@Comment("订单序列号")
|
||||||
|
@Column(value = "order_seq")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 64)
|
||||||
|
private String orderSeq;
|
||||||
|
|
||||||
|
@Comment("卡类型")
|
||||||
|
@Column(value = "card_typ")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 16)
|
||||||
|
private String cardTyp;
|
||||||
|
|
||||||
|
@Comment("支付时间(银行原始字符串 yyyyMMddHHmmss)")
|
||||||
|
@Column(value = "pay_time")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String payTime;
|
||||||
|
|
||||||
|
@Comment("订单状态")
|
||||||
|
@Column(value = "order_status")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 16)
|
||||||
|
private String orderStatus;
|
||||||
|
|
||||||
|
@Comment("支付金额(银行原始字符串)")
|
||||||
|
@Column(value = "pay_amount")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String payAmount;
|
||||||
|
|
||||||
|
@Comment("订单IP")
|
||||||
|
@Column(value = "order_ip")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 64)
|
||||||
|
private String orderIp;
|
||||||
|
|
||||||
|
@Comment("订单引用")
|
||||||
|
@Column(value = "order_refer")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 255)
|
||||||
|
private String orderRefer;
|
||||||
|
|
||||||
|
@Comment("银行交易流水号")
|
||||||
|
@Column(value = "bank_tran_seq")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 64)
|
||||||
|
private String bankTranSeq;
|
||||||
|
|
||||||
|
@Comment("操作类型标志")
|
||||||
|
@Column(value = "return_act_flag")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 16)
|
||||||
|
private String returnActFlag;
|
||||||
|
|
||||||
|
@Comment("手机号")
|
||||||
|
@Column(value = "phone_num")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String phoneNum;
|
||||||
|
|
||||||
|
@Comment("银联流水号")
|
||||||
|
@Column(value = "union_pay_seq")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 64)
|
||||||
|
private String unionPaySeq;
|
||||||
|
|
||||||
|
@Comment("签名数据(银行回传 Base64)")
|
||||||
|
@Column(value = "sign_data")
|
||||||
|
@ColDefine(type = ColType.TEXT)
|
||||||
|
private String signData;
|
||||||
|
|
||||||
|
@Comment("验签结果: 1=通过 0=失败 NULL=未验签")
|
||||||
|
@Column(value = "verify_result")
|
||||||
|
@ColDefine(type = ColType.INT)
|
||||||
|
private Integer verifyResult;
|
||||||
|
|
||||||
|
@Comment("处理结果说明")
|
||||||
|
@Column(value = "handle_result")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 500)
|
||||||
|
private String handleResult;
|
||||||
|
|
||||||
|
@Comment("创建时间")
|
||||||
|
@Column(value = "create_time")
|
||||||
|
@ColDefine(type = ColType.TIMESTAMP)
|
||||||
|
private Date createTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package io.v.nutz.pay.bank.china.pojo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class RefundOrderResponse implements Serializable {
|
||||||
|
|
||||||
|
private String merchantNo;
|
||||||
|
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
private String mRefundSeq;
|
||||||
|
|
||||||
|
private String orderStatus;
|
||||||
|
|
||||||
|
private String refundAmount;
|
||||||
|
|
||||||
|
private String orderSeq;
|
||||||
|
|
||||||
|
private String bankTranSeq;
|
||||||
|
|
||||||
|
private String unionPaySeq;
|
||||||
|
|
||||||
|
private String hdlSts;
|
||||||
|
|
||||||
|
private String rtnMsg;
|
||||||
|
|
||||||
|
private String bdFlg;
|
||||||
|
|
||||||
|
private String signData;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package io.v.nutz.pay.bank.china.service;
|
||||||
|
|
||||||
|
import io.v.nutz.base.service.BaseService;
|
||||||
|
import io.v.nutz.pay.bank.china.module.ChinaBankPayNotifyRecord;
|
||||||
|
|
||||||
|
public interface IChinaBankPayNotifyRecordService extends BaseService<ChinaBankPayNotifyRecord> {
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
package io.v.nutz.pay.bank.china.service.impl;
|
||||||
|
|
||||||
|
import io.v.nutz.base.service.impl.BaseServiceImpl;
|
||||||
|
import io.v.nutz.pay.bank.china.module.ChinaBankPayNotifyRecord;
|
||||||
|
import io.v.nutz.pay.bank.china.service.IChinaBankPayNotifyRecordService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@IocBean(args = {"refer:dao"})
|
||||||
|
public class ChinaBankPayNotifyRecordServiceImpl
|
||||||
|
extends BaseServiceImpl<ChinaBankPayNotifyRecord>
|
||||||
|
implements IChinaBankPayNotifyRecordService {
|
||||||
|
|
||||||
|
public ChinaBankPayNotifyRecordServiceImpl(Dao dao) {
|
||||||
|
super(dao);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,19 @@
|
|||||||
package io.v.nutz.pay.record.controller;
|
package io.v.nutz.pay.record.controller;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.wizzer.framework.base.Result;
|
import cn.wizzer.framework.base.Result;
|
||||||
import io.v.nutz.pay.annotations.Api;
|
import io.v.nutz.pay.annotations.Api;
|
||||||
import io.v.nutz.pay.annotations.ApiOperation;
|
import io.v.nutz.pay.annotations.ApiOperation;
|
||||||
|
import io.v.nutz.pay.bank.china.BankChinaWxPayService;
|
||||||
|
import io.v.nutz.pay.bank.china.pojo.RefundOrderResponse;
|
||||||
|
import io.v.nutz.pay.bank.china.pojo.WxPayOrderQueryResponse;
|
||||||
import io.v.nutz.pay.cache.ChinaBankOrderWaitPayCacheService;
|
import io.v.nutz.pay.cache.ChinaBankOrderWaitPayCacheService;
|
||||||
|
import io.v.nutz.pay.common.CommonConstants;
|
||||||
import io.v.nutz.pay.enums.ChannelTypeEnum;
|
import io.v.nutz.pay.enums.ChannelTypeEnum;
|
||||||
import io.v.nutz.pay.enums.MemberPayBusinessTypeEnum;
|
import io.v.nutz.pay.enums.MemberPayBusinessTypeEnum;
|
||||||
|
import io.v.nutz.pay.enums.MemberPayStatusEnum;
|
||||||
import io.v.nutz.pay.enums.PayChannelEnum;
|
import io.v.nutz.pay.enums.PayChannelEnum;
|
||||||
import io.v.nutz.pay.form.PayRecordForm;
|
import io.v.nutz.pay.form.PayRecordForm;
|
||||||
import io.v.nutz.pay.pojo.LoginUser;
|
import io.v.nutz.pay.pojo.LoginUser;
|
||||||
@@ -15,6 +21,8 @@ import io.v.nutz.pay.record.module.MemberPayRecord;
|
|||||||
import io.v.nutz.pay.record.service.IMemberPayRecordService;
|
import io.v.nutz.pay.record.service.IMemberPayRecordService;
|
||||||
import io.v.nutz.pay.util.AuthUtil;
|
import io.v.nutz.pay.util.AuthUtil;
|
||||||
import io.v.nutz.pay.util.ServletUtil;
|
import io.v.nutz.pay.util.ServletUtil;
|
||||||
|
import io.v.nutz.zhgh.memberCost.model.MemberPaymentInfo;
|
||||||
|
import io.v.nutz.zhgh.memberCost.service.MemberPaymentService;
|
||||||
import org.nutz.integration.jedis.RedisService;
|
import org.nutz.integration.jedis.RedisService;
|
||||||
import org.nutz.ioc.loader.annotation.Inject;
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
import org.nutz.ioc.loader.annotation.IocBean;
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
@@ -42,6 +50,12 @@ public class MemberPayRecordController {
|
|||||||
@Inject
|
@Inject
|
||||||
private ChinaBankOrderWaitPayCacheService chinaBankOrderWaitPayCacheService;
|
private ChinaBankOrderWaitPayCacheService chinaBankOrderWaitPayCacheService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BankChinaWxPayService bankChinaWxPayService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private MemberPaymentService memberPaymentService;
|
||||||
|
|
||||||
|
|
||||||
@Ok("json")
|
@Ok("json")
|
||||||
@At("/get/by/code")
|
@At("/get/by/code")
|
||||||
@@ -107,4 +121,122 @@ public class MemberPayRecordController {
|
|||||||
chinaBankOrderWaitPayCacheService.delItem(payCode, 60 * 60 * 24);
|
chinaBankOrderWaitPayCacheService.delItem(payCode, 60 * 60 * 24);
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@At("/refund")
|
||||||
|
@Ok("json")
|
||||||
|
@ApiOperation("支付记录退款(调用银行退款接口)")
|
||||||
|
public Result refund(String goodsTradeCode, Double refundAmount, HttpServletRequest request) {
|
||||||
|
Assert.isTrue(StrUtil.isNotBlank(goodsTradeCode), "缺少商品交易单号");
|
||||||
|
Assert.notNull(refundAmount, "缺少退款金额");
|
||||||
|
Assert.isTrue(refundAmount > 0, "退款金额必须大于0");
|
||||||
|
|
||||||
|
// 查询支付记录
|
||||||
|
MemberPayRecord record = memberPayRecordService.getByGoodsTradeCode(goodsTradeCode);
|
||||||
|
if (record == null) {
|
||||||
|
return Result.error("支付记录不存在");
|
||||||
|
}
|
||||||
|
if (!MemberPayStatusEnum.SUCCESS.getCode().equals(record.getStatus())) {
|
||||||
|
return Result.error("支付记录状态不支持退款");
|
||||||
|
}
|
||||||
|
if (record.getPayMoney() != null && refundAmount > record.getPayMoney()) {
|
||||||
|
return Result.error("退款金额不能大于支付金额");
|
||||||
|
}
|
||||||
|
|
||||||
|
LoginUser loginUser = AuthUtil.instance().getLoginUser();
|
||||||
|
if (loginUser == null || StrUtil.isBlank(loginUser.getId())) {
|
||||||
|
throw new RuntimeException("用户登录失效,请重新登录");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 终端IP
|
||||||
|
String deviceIp = ServletUtil.getIp(request);
|
||||||
|
|
||||||
|
try {
|
||||||
|
RefundOrderResponse resp;
|
||||||
|
// 中国银行支付渠道
|
||||||
|
if (PayChannelEnum.CHINA_BANK.getCode().equals(record.getPayChannel())) {
|
||||||
|
resp = bankChinaWxPayService.refundOrder(goodsTradeCode, refundAmount, deviceIp);
|
||||||
|
} else {
|
||||||
|
return Result.error("不支持该支付渠道退款");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新支付记录状态为已退款
|
||||||
|
record.setStatus(MemberPayStatusEnum.REFUND.getCode());
|
||||||
|
record.setLastRefundTime(DateUtil.date());
|
||||||
|
record.setRefundMoney(refundAmount);
|
||||||
|
record.setStatusReason("退款成功");
|
||||||
|
memberPayRecordService.update(record);
|
||||||
|
|
||||||
|
// 退款后重置会员缴费信息为未缴费: business_id 即 member_payment_info.id
|
||||||
|
if (MemberPayBusinessTypeEnum.UNION_PAYMENT.getCode().equals(record.getBusinessType())
|
||||||
|
&& StrUtil.isNotBlank(record.getBusinessId())) {
|
||||||
|
MemberPaymentInfo paymentInfo = memberPaymentService.fetch(record.getBusinessId());
|
||||||
|
if (paymentInfo != null) {
|
||||||
|
paymentInfo.setPayment(false);
|
||||||
|
memberPaymentService.update(paymentInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.success(resp);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@At("/query/order")
|
||||||
|
@Ok("json")
|
||||||
|
@ApiOperation("银行查询订单交易状态(PGWPortal/QueryOrderTrans.do)")
|
||||||
|
public Result queryOrderByBank(String goodsTradeCode) {
|
||||||
|
Assert.isTrue(StrUtil.isNotBlank(goodsTradeCode), "缺少商品交易单号");
|
||||||
|
|
||||||
|
// 查询本地支付记录,校验记录存在及渠道类型
|
||||||
|
MemberPayRecord record = memberPayRecordService.getByGoodsTradeCode(goodsTradeCode);
|
||||||
|
if (record == null) {
|
||||||
|
return Result.error("支付记录不存在");
|
||||||
|
}
|
||||||
|
if (!PayChannelEnum.CHINA_BANK.getCode().equals(record.getPayChannel())) {
|
||||||
|
return Result.error("不支持该支付渠道查询");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 调用银行查询接口
|
||||||
|
WxPayOrderQueryResponse response = bankChinaWxPayService.queryOrder(goodsTradeCode);
|
||||||
|
|
||||||
|
// 根据银行返回的交易状态同步更新本地支付记录
|
||||||
|
// 仅在本地记录仍为待支付状态时才同步,避免通知已处理后重复累加 payMoney
|
||||||
|
Integer currentStatus = record.getStatus();
|
||||||
|
boolean needSync = MemberPayStatusEnum.WAIT.getCode().equals(currentStatus);
|
||||||
|
|
||||||
|
String tranStatus = response.getTranStatus();
|
||||||
|
if (needSync && tranStatus != null
|
||||||
|
&& (tranStatus.equals(CommonConstants.ONE.toString()) || tranStatus.equals(CommonConstants.TWO.toString()))) {
|
||||||
|
|
||||||
|
if (tranStatus.equals(CommonConstants.ONE.toString())) {
|
||||||
|
// 支付成功
|
||||||
|
Double payAmount = response.getTranAmount() != null
|
||||||
|
? Double.valueOf(response.getTranAmount()) : record.getPayMoney();
|
||||||
|
memberPayRecordService.paySuccess(goodsTradeCode, payAmount);
|
||||||
|
|
||||||
|
// 同步更新会员缴费信息为已缴费
|
||||||
|
if (MemberPayBusinessTypeEnum.UNION_PAYMENT.getCode().equals(record.getBusinessType())
|
||||||
|
&& StrUtil.isNotBlank(record.getBusinessId())) {
|
||||||
|
MemberPaymentInfo paymentInfo = memberPaymentService.fetch(record.getBusinessId());
|
||||||
|
if (paymentInfo != null) {
|
||||||
|
paymentInfo.setPayment(true);
|
||||||
|
memberPaymentService.update(paymentInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// 支付失败
|
||||||
|
memberPayRecordService.payFail(goodsTradeCode, "银行查询结果:支付失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.success(response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return Result.error(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public class NutShiroProcessor extends AbstractProcessor {
|
|||||||
"/platform/qywechat/.*",
|
"/platform/qywechat/.*",
|
||||||
"/platform/wechat/.*",
|
"/platform/wechat/.*",
|
||||||
"/platform/home/(500|403|404|UnknownAccountError|LockedAccountError)",
|
"/platform/home/(500|403|404|UnknownAccountError|LockedAccountError)",
|
||||||
"/mobile/login",
|
// "/mobile/login",
|
||||||
"/mobile/login/doLogin",
|
"/mobile/login/doLogin",
|
||||||
"/platform/jsz/login",
|
"/platform/jsz/login",
|
||||||
"/platform/activity/basic/scope/getScopeUser",
|
"/platform/activity/basic/scope/getScopeUser",
|
||||||
|
|||||||
+11
-11
@@ -273,7 +273,7 @@ public class ActivityApplyController {
|
|||||||
Sql applySql = Sqls.create("""
|
Sql applySql = Sqls.create("""
|
||||||
SELECT
|
SELECT
|
||||||
asa.*
|
asa.*
|
||||||
|
|
||||||
FROM
|
FROM
|
||||||
activity_school_apply asa
|
activity_school_apply asa
|
||||||
LEFT JOIN activity_school_team team ON asa.teamId = team.id
|
LEFT JOIN activity_school_team team ON asa.teamId = team.id
|
||||||
@@ -308,7 +308,7 @@ public class ActivityApplyController {
|
|||||||
cndTeam.and("activityId", "=", activityId);
|
cndTeam.and("activityId", "=", activityId);
|
||||||
List<ActivitySchoolTeam> teamList = activitySchoolTeamService.dao().query(ActivitySchoolTeam.class, cndTeam.orderBy("CAST(SUBSTRING(name FROM 2 FOR LOCATE('队', name) - 2) AS UNSIGNED)", "ASC"));
|
List<ActivitySchoolTeam> teamList = activitySchoolTeamService.dao().query(ActivitySchoolTeam.class, cndTeam.orderBy("CAST(SUBSTRING(name FROM 2 FOR LOCATE('队', name) - 2) AS UNSIGNED)", "ASC"));
|
||||||
|
|
||||||
if (activity.getApplyMultipleTeamsUnionIds().contains(Vi.getUnionId())) {
|
if (Lang.isNotEmpty(activity.getApplyMultipleTeamsUnionIds()) && activity.getApplyMultipleTeamsUnionIds().contains(Vi.getUnionId())) {
|
||||||
result.put("team", teamList);
|
result.put("team", teamList);
|
||||||
} else {
|
} else {
|
||||||
result.put("team", Lang.isNotEmpty(teamList) ? List.of(teamList.get(0)) : teamList);
|
result.put("team", Lang.isNotEmpty(teamList) ? List.of(teamList.get(0)) : teamList);
|
||||||
@@ -575,15 +575,15 @@ public class ActivityApplyController {
|
|||||||
public Object findUserOne(String id) {
|
public Object findUserOne(String id) {
|
||||||
try {
|
try {
|
||||||
Sql sql = Sqls.create("SELECT\n" +
|
Sql sql = Sqls.create("SELECT\n" +
|
||||||
"\tu.id,u.username,u.unitid,\n" +
|
"\tu.id,u.username,u.unitid,\n" +
|
||||||
"\tu.loginname,\n" +
|
"\tu.loginname,\n" +
|
||||||
"\tu.sex,\n" +
|
"\tu.sex,\n" +
|
||||||
"\tu.mobile,\n" +
|
"\tu.mobile,\n" +
|
||||||
"\tu.position,\n" +
|
"\tu.position,\n" +
|
||||||
"\tun.`name` unitname \n" +
|
"\tun.`name` unitname \n" +
|
||||||
"FROM\n" +
|
"FROM\n" +
|
||||||
"\tsys_user u\n" +
|
"\tsys_user u\n" +
|
||||||
"\tLEFT JOIN sys_unit un ON u.unitid = un.id Where u.id = @id").setParam("id", id);
|
"\tLEFT JOIN sys_unit un ON u.unitid = un.id Where u.id = @id").setParam("id", id);
|
||||||
|
|
||||||
return Result.success().addData(activitySchoolService.list(sql).get(0));
|
return Result.success().addData(activitySchoolService.list(sql).get(0));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -331,18 +331,18 @@ layout("/layouts/platform.html"){
|
|||||||
|
|
||||||
</template>
|
</template>
|
||||||
<template #func>
|
<template #func>
|
||||||
<!-- <div class="mr10" v-if="unionLeaderCoach">-->
|
<div class="mr10" v-if="unionLeaderCoach">
|
||||||
<!-- <!–团长:<span style="color: #419BF8">{{headData.username | str}}</span> –>–>-->
|
<!--团长:<span style="color: #419BF8">{{headData.username | str}}</span> –>-->
|
||||||
<!-- 领队兼教练:<span style="color: #419BF8">{{LeaderData.username | str}} </span> -->
|
领队兼教练:<span style="color: #419BF8">{{LeaderData.username | str}} </span> 
|
||||||
<!--<!– 教练:<span style="color: #419BF8">{{CoachData.username | str}}</span>–>-->
|
<!-- 教练:<span style="color: #419BF8">{{CoachData.username | str}}</span>-->
|
||||||
<!-- <!– 工作人员:<span-->
|
<!-- 工作人员:<span
|
||||||
<!-- style="color: #419BF8">{{staffData.username | str}}</span>–>-->
|
style="color: #419BF8">{{staffData.username | str}}</span>-->
|
||||||
<!-- </div>-->
|
</div>
|
||||||
<!-- <div>-->
|
<div>
|
||||||
<!-- <el-button @click="openLeaderCoach" type="primary"-->
|
<el-button @click="openLeaderCoach" type="primary"
|
||||||
<!-- v-if="unionLeaderCoach">设置领队/教练-->
|
v-if="unionLeaderCoach">设置领队/教练
|
||||||
<!-- </el-button>-->
|
</el-button>
|
||||||
<!-- </div>-->
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
</table-tool>
|
</table-tool>
|
||||||
|
|||||||
Reference in New Issue
Block a user