记得上下班打卡 | git大法好,push需谨慎

Commit e7aced79 authored by zhengfuxin's avatar zhengfuxin

修改notify配置文件。和复制支付代码。

parent ef113520
...@@ -37,51 +37,9 @@ liquidnet: ...@@ -37,51 +37,9 @@ liquidnet:
appId: wx3498304dda39c5a1 appId: wx3498304dda39c5a1
partnerKey: itIuO65O9yKmemOu3S8g1S4orqvCGwXK partnerKey: itIuO65O9yKmemOu3S8g1S4orqvCGwXK
unionpay: unionpay:
merchantId: 777290058194736 merchantId: 821690048160PQY
gateway-url: https://gateway.test.95516.com gateway-url: https://gateway.95516.com
certs-path: /data/certs/dragon/unionpay/dev refund-url: https://gateway.95516.com/
# ---------------------以下为银联支付-------------------------------------- certs-path: /data/certs/dragon/unionpay/test
##交易请求地址 certs-prefix: acp_prod
acpsdk: pfx-pwd: '520360'
## 消费接口
frontTransUrl: ${liquidnet.dragon.unionpay.gateway-url}/gateway/api/frontTransReq.do
## app 消费接口
appTransUrl: ${liquidnet.dragon.unionpay.gateway-url}/gateway/api/appTransReq.do
## 交易状态查询
backTransUrl: ${liquidnet.dragon.unionpay.gateway-url}/gateway/api/backTransReq.do
## 交易状态查询:app用的路径
singleQueryUrl: ${liquidnet.dragon.unionpay.gateway-url}/gateway/api/queryTrans.do
## 退款路径 (https://gateway.95516.com/gateway/api/backTransReq.do)
refundUrl: https://101.231.204.80:5000/gateway/api/backTransReq.do
########################################################################
########################################################################
# 报文版本号,固定5.1.0,请勿改动
version: 5.1.0
# 签名方式,证书方式固定01,请勿改动
signMethod: '01'
# 是否验证验签证书的CN,测试环境请设置false,生产环境请设置true。非false的值默认都当true处理。
ifValidateCNName: false
# 是否验证https证书,测试环境请设置false,生产环境建议优先尝试true,不行再false。非true的值默认都当false处理。
ifValidateRemoteCert: false
#后台通知地址,填写接收银联后台通知的地址,必须外网能访问
#backUrl: http://222.222.222.222:8080/ACPSample_AppServer/backRcvResponse
#前台通知地址,填写处理银联前台通知的地址,必须外网能访问
#frontUrl: http://localhost:8080/ACPSample_AppServer/frontRcvResponse
#########################入网测试环境签名证书配置 ################################
# 多证书的情况证书路径为代码指定,可不对此块做配置。
# 签名证书路径,必须使用绝对路径,如果不想使用绝对路径,可以自行实现相对路径获取证书的方法;测试证书所有商户共用开发包中的测试签名证书,生产环境请从cfca下载得到。
# windows样例:
signCertPath: ${liquidnet.dragon.unionpay.certs-path}/acp_test_sign.pfx
# 签名证书密码,测试环境固定000000,生产环境请修改为从cfca下载的正式证书的密码,正式环境证书密码位数需小于等于6位,否则上传到商户服务网站会失败
signCertPwd: '000000'
# 签名证书类型,固定不需要修改
signCertType: PKCS12
##########################加密证书配置################################
# 敏感信息加密证书路径(商户号开通了商户对敏感信息加密的权限,需要对 卡号accNo,pin和phoneNo,cvn2,expired加密(如果这些上送的话),对敏感信息加密使用)
encryptCertPath: ${liquidnet.dragon.unionpay.certs-path}/acp_test_enc.cer
##########################验签证书配置################################
# 验签中级证书路径(银联提供)
middleCertPath: ${liquidnet.dragon.unionpay.certs-path}/acp_test_middle.cer
# 验签根证书路径(银联提供)
rootCertPath: ${liquidnet.dragon.unionpay.certs-path}/acp_test_root.cer
...@@ -105,3 +105,49 @@ global-auth: ...@@ -105,3 +105,49 @@ global-auth:
# ----------------------------------------------------------- # -----------------------------------------------------------
# ----------------------------------------------------------- # -----------------------------------------------------------
# -----------------------------------------------------------
# ---------------------以下为银联支付--------------------------------------
##交易请求地址
acpsdk:
## 消费接口
frontTransUrl: ${liquidnet.dragon.unionpay.gateway-url}/gateway/api/frontTransReq.do
## app 消费接口
appTransUrl: ${liquidnet.dragon.unionpay.gateway-url}/gateway/api/appTransReq.do
## 交易状态查询
backTransUrl: ${liquidnet.dragon.unionpay.gateway-url}/gateway/api/backTransReq.do
## 交易状态查询:app用的路径
singleQueryUrl: ${liquidnet.dragon.unionpay.gateway-url}/gateway/api/queryTrans.do
## 退款路径 (https://gateway.95516.com/gateway/api/backTransReq.do)
refundUrl: ${liquidnet.dragon.unionpay.refund-url}/gateway/api/backTransReq.do
########################################################################
########################################################################
# 报文版本号,固定5.1.0,请勿改动
version: 5.1.0
# 签名方式,证书方式固定01,请勿改动
signMethod: '01'
# 是否验证验签证书的CN,测试环境请设置false,生产环境请设置true。非false的值默认都当true处理。
ifValidateCNName: false
# 是否验证https证书,测试环境请设置false,生产环境建议优先尝试true,不行再false。非true的值默认都当false处理。
ifValidateRemoteCert: false
#后台通知地址,填写接收银联后台通知的地址,必须外网能访问
#backUrl: http://222.222.222.222:8080/ACPSample_AppServer/backRcvResponse
#前台通知地址,填写处理银联前台通知的地址,必须外网能访问
#frontUrl: http://localhost:8080/ACPSample_AppServer/frontRcvResponse
#########################入网测试环境签名证书配置 ################################
# 多证书的情况证书路径为代码指定,可不对此块做配置。
# 签名证书路径,必须使用绝对路径,如果不想使用绝对路径,可以自行实现相对路径获取证书的方法;测试证书所有商户共用开发包中的测试签名证书,生产环境请从cfca下载得到。
# windows样例:
signCertPath: ${liquidnet.dragon.unionpay.certs-path}/${liquidnet.dragon.unionpay.certs-prefix}_sign.pfx
# 签名证书密码,测试环境固定000000,生产环境请修改为从cfca下载的正式证书的密码,正式环境证书密码位数需小于等于6位,否则上传到商户服务网站会失败
signCertPwd: ${liquidnet.dragon.unionpay.pfx-pwd}
# 签名证书类型,固定不需要修改
signCertType: PKCS12
##########################加密证书配置################################
# 敏感信息加密证书路径(商户号开通了商户对敏感信息加密的权限,需要对 卡号accNo,pin和phoneNo,cvn2,expired加密(如果这些上送的话),对敏感信息加密使用)
encryptCertPath: ${liquidnet.dragon.unionpay.certs-path}/${liquidnet.dragon.unionpay.certs-prefix}_enc.cer
##########################验签证书配置################################
# 验签中级证书路径(银联提供)
middleCertPath: ${liquidnet.dragon.unionpay.certs-path}/${liquidnet.dragon.unionpay.certs-prefix}_middle.cer
# 验签根证书路径(银联提供)
rootCertPath: ${liquidnet.dragon.unionpay.certs-path}/${liquidnet.dragon.unionpay.certs-prefix}_root.cer
\ No newline at end of file
...@@ -94,10 +94,19 @@ public class UnionpayBiz { ...@@ -94,10 +94,19 @@ public class UnionpayBiz {
// 超过超时时间调查询接口应答origRespCode不是A6或者00的就可以判断为失败。 // 超过超时时间调查询接口应答origRespCode不是A6或者00的就可以判断为失败。
//requestData.put("payTimeout", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date().getTime() + 15 * 60 * 1000)); //requestData.put("payTimeout", new SimpleDateFormat("yyyyMMddHHmmss").format(new Date().getTime() + 15 * 60 * 1000));
requestData.put("payTimeout", payReq.getPayTimeout()); requestData.put("payTimeout", payReq.getPayTimeout());
//20211207140900
/**请求参数设置完毕,以下对请求参数进行签名并生成html表单,将表单写入浏览器跳转打开银联页面**/ /**请求参数设置完毕,以下对请求参数进行签名并生成html表单,将表单写入浏览器跳转打开银联页面**/
Map<String, String> submitFromData = acpService.sign(requestData,UnionpayConstant.encoding); //报文中certId,signature的值是在signData方法中获取并自动赋值的,只要证书配置正确即可。 Map<String, String> submitFromData = acpService.sign(requestData,UnionpayConstant.encoding); //报文中certId,signature的值是在signData方法中获取并自动赋值的,只要证书配置正确即可。
/* //获取请求银联的前台地址:对应属性文件acp_sdk.properties文件中的acpsdk.frontTransUrl
String requestFrontUrl = "https://gateway.test.95516.com/gateway/api/frontTransReq.do";
//生成自动跳转的Html表单
String html = AcpService.createAutoFormHtml(requestFrontUrl, submitFromData,"encoding_UTF8");
log.info("生成的html{}",html);*/
//将生成的html写到浏览器中完成自动跳转打开银联支付页面;这里调用signData之后,将html写到浏览器跳转到银联页面之前均不能对html中的表单项的名称和值进行修改,如果修改会导致验签不通过 //将生成的html写到浏览器中完成自动跳转打开银联支付页面;这里调用signData之后,将html写到浏览器跳转到银联页面之前均不能对html中的表单项的名称和值进行修改,如果修改会导致验签不通过
return submitFromData; return submitFromData;
......
package com.liquidnet.service.dragon.channel.unionpay.strategy.impl; package com.liquidnet.service.dragon.channel.unionpay.strategy.impl;
import com.liquidnet.common.exception.LiquidnetServiceException; import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.JsonUtils; import com.liquidnet.commons.lang.util.DateUtil;
import com.liquidnet.commons.lang.util.StringUtil; import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz; import com.liquidnet.service.dragon.channel.strategy.biz.DragonPayBiz;
import com.liquidnet.service.dragon.channel.unionpay.biz.UnionpayBiz; import com.liquidnet.service.dragon.channel.unionpay.biz.UnionpayBiz;
...@@ -65,8 +65,15 @@ public class UnionpayStrategyAppImpl extends AbstractUnionPayStrategy { ...@@ -65,8 +65,15 @@ public class UnionpayStrategyAppImpl extends AbstractUnionPayStrategy {
@Override @Override
UnionpayTradePayReq appendRequestParam(UnionpayTradePayReq payReq, DragonPayBaseReqDto dragonPayBaseReqDto) { UnionpayTradePayReq appendRequestParam(UnionpayTradePayReq payReq, DragonPayBaseReqDto dragonPayBaseReqDto) {
payReq.setAccType("01"); /* payReq.setAccType("01");
payReq.setChannelType("08"); payReq.setChannelType("08");*/
//设置订单过期时间
String timeExpire = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(dragonPayBaseReqDto.getCreateDate()).plusMinutes(Long.parseLong(dragonPayBaseReqDto.getExpireTime())),DateUtil.Formatter.yyyyMMddHHmmssTrim);
payReq.setChannelType("07");
payReq.setRiskRateInfo(dragonPayBaseReqDto.getName());
payReq.setFrontUrl(dragonPayBaseReqDto.getReturnUrl());
payReq.setPayTimeout(timeExpire);
return payReq; return payReq;
} }
/** /**
...@@ -109,9 +116,10 @@ public class UnionpayStrategyAppImpl extends AbstractUnionPayStrategy { ...@@ -109,9 +116,10 @@ public class UnionpayStrategyAppImpl extends AbstractUnionPayStrategy {
/* if(StringUtil.isNotNull(respResult)&&respResult.get("tn")!=null){ /* if(StringUtil.isNotNull(respResult)&&respResult.get("tn")!=null){
payBaseRespDto.getPayData().setPrepayId(respResult.get("tn")); payBaseRespDto.getPayData().setPrepayId(respResult.get("tn"));
}*/ }*/
payBaseRespDto.getPayData().setRedirectUrl(sdkConfig.getFrontTransUrl()); payBaseRespDto.getPayData().setRedirectUrl(sdkConfig.getFrontTransUrl());
if(StringUtil.isNotNull(respResult)){ if(StringUtil.isNotNull(respResult)){
payBaseRespDto.getPayData().setOrderStr(JsonUtils.toJson(respResult)); payBaseRespDto.getPayData().setPrepayId(respResult.get("tn"));
} }
return payBaseRespDto; return payBaseRespDto;
......
...@@ -67,7 +67,7 @@ public class UnionpayStrategyWapImpl extends AbstractUnionPayStrategy { ...@@ -67,7 +67,7 @@ public class UnionpayStrategyWapImpl extends AbstractUnionPayStrategy {
@Override @Override
UnionpayTradePayReq appendRequestParam(UnionpayTradePayReq payReq, DragonPayBaseReqDto dragonPayBaseReqDto) { UnionpayTradePayReq appendRequestParam(UnionpayTradePayReq payReq, DragonPayBaseReqDto dragonPayBaseReqDto) {
//设置订单过期时间 //设置订单过期时间
String timeExpire = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(dragonPayBaseReqDto.getCreateDate()).plusMinutes(Long.parseLong(dragonPayBaseReqDto.getExpireTime())),DateUtil.Formatter.yyyyMMddHHmmss); String timeExpire = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(dragonPayBaseReqDto.getCreateDate()).plusMinutes(Long.parseLong(dragonPayBaseReqDto.getExpireTime())),DateUtil.Formatter.yyyyMMddHHmmssTrim);
payReq.setChannelType("07"); payReq.setChannelType("07");
payReq.setRiskRateInfo(dragonPayBaseReqDto.getName()); payReq.setRiskRateInfo(dragonPayBaseReqDto.getName());
payReq.setFrontUrl(dragonPayBaseReqDto.getReturnUrl()); payReq.setFrontUrl(dragonPayBaseReqDto.getReturnUrl());
...@@ -110,7 +110,7 @@ public class UnionpayStrategyWapImpl extends AbstractUnionPayStrategy { ...@@ -110,7 +110,7 @@ public class UnionpayStrategyWapImpl extends AbstractUnionPayStrategy {
payBaseRespDto.getPayData().setRedirectUrl(sdkConfig.getFrontTransUrl()); payBaseRespDto.getPayData().setRedirectUrl(sdkConfig.getFrontTransUrl());
if(StringUtil.isNotNull(respResult)){ if(StringUtil.isNotNull(respResult)){
payBaseRespDto.getPayData().setOrderStr(JsonUtils.toJson(respResult)); payBaseRespDto.getPayData().setPrepayId(JsonUtils.toJson(respResult));
} }
return payBaseRespDto; return payBaseRespDto;
} }
......
/*
package com.liquidnet.service.dragon.controller; package com.liquidnet.service.dragon.controller;
import com.liquidnet.commons.lang.util.StringUtil; import com.liquidnet.commons.lang.util.StringUtil;
...@@ -20,6 +21,7 @@ import java.math.BigDecimal; ...@@ -20,6 +21,7 @@ import java.math.BigDecimal;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
*/
/** /**
* @author AnJiabin <anjiabin@zhengzai.tv> * @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0 * @version V1.0
...@@ -28,18 +30,21 @@ import java.util.Map; ...@@ -28,18 +30,21 @@ import java.util.Map;
* @Package com.liquidnet.service.dragon.controller * @Package com.liquidnet.service.dragon.controller
* @Copyright: LightNet @ Copyright (c) 2021 * @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/7/9 12:29 * @date 2021/7/9 12:29
*/ *//*
@Slf4j @Slf4j
@RestController @RestController
@RequestMapping("pay") @RequestMapping("pay")
public class PayController { public class PayController {
/* @Autowired @Autowired
private IDragonOrdersService dragonOrdersService; private IDragonOrdersService dragonOrdersService;
*//** */
/**
* 电脑网页支付宝支付 * 电脑网页支付宝支付
* @return * @return
*//* *//*
@PostMapping("/dragonPay") @PostMapping("/dragonPay")
@ApiOperation("Dragon支付") @ApiOperation("Dragon支付")
@ApiResponse(code = 200, message = "接口返回对象参数") @ApiResponse(code = 200, message = "接口返回对象参数")
...@@ -148,5 +153,6 @@ public class PayController { ...@@ -148,5 +153,6 @@ public class PayController {
rs.put("code",code); rs.put("code",code);
rs.put("result",""+respDto); rs.put("result",""+respDto);
return ResponseDto.success(rs); return ResponseDto.success(rs);
}*/ }
} }
*/
...@@ -120,9 +120,11 @@ public class DragonOrderRefundsServiceImpl implements IDragonOrderRefundsService ...@@ -120,9 +120,11 @@ public class DragonOrderRefundsServiceImpl implements IDragonOrderRefundsService
dto = douYinRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localDouYinCallBackUrl, nowTime); dto = douYinRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localDouYinCallBackUrl, nowTime);
break; break;
case DragonConstant.REFUND_TYPE_WAP_UNION: case DragonConstant.REFUND_TYPE_WAP_UNION:
dataUtils.setOrderCode(orderRefundCode,orderCode);
dto =UnionWapPayRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localUnionPayCallBackUrl, nowTime); dto =UnionWapPayRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localUnionPayCallBackUrl, nowTime);
break; break;
case DragonConstant.REFUND_TYPE_APP_UNION: case DragonConstant.REFUND_TYPE_APP_UNION:
dataUtils.setOrderCode(orderRefundCode,orderCode);
dto =UnionWapPayRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localUnionPayCallBackUrl, nowTime); dto =UnionWapPayRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localUnionPayCallBackUrl, nowTime);
break; break;
} }
...@@ -282,7 +284,7 @@ public class DragonOrderRefundsServiceImpl implements IDragonOrderRefundsService ...@@ -282,7 +284,7 @@ public class DragonOrderRefundsServiceImpl implements IDragonOrderRefundsService
data.put("orderId", refundCode); //商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生,不同于原消费 data.put("orderId", refundCode); //商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生,不同于原消费
data.put("txnTime", txnTime); //订单发送时间,格式为yyyyMMddHHmmss,必须取当前时间,否则会报txnTime无效 data.put("txnTime", txnTime); //订单发送时间,格式为yyyyMMddHHmmss,必须取当前时间,否则会报txnTime无效
data.put("currencyCode", "156"); //交易币种(境内商户一般是156 人民币) data.put("currencyCode", "156"); //交易币种(境内商户一般是156 人民币)
data.put("txnAmt", (price.doubleValue() * 100) + ""); //交易金额 单位为分 data.put("txnAmt", price.multiply(BigDecimal.valueOf(100L)).intValue() + ""); //交易金额 单位为分
data.put("backUrl", notifyUrl); //后台通知地址,后台通知参数详见open.unionpay.com帮助中心 下载 产品接口规范 网关支付产品接口规范 退货交易 商户通知,其他说明同消费交易的后台通知 data.put("backUrl", notifyUrl); //后台通知地址,后台通知参数详见open.unionpay.com帮助中心 下载 产品接口规范 网关支付产品接口规范 退货交易 商户通知,其他说明同消费交易的后台通知
/***要调通交易以下字段必须修改***/ /***要调通交易以下字段必须修改***/
data.put("origQryId", paymentId); //****原消费交易返回的的queryId,可以从消费交易后台通知接口中或者交易状态查询接口中获取 data.put("origQryId", paymentId); //****原消费交易返回的的queryId,可以从消费交易后台通知接口中或者交易状态查询接口中获取
...@@ -312,13 +314,13 @@ public class DragonOrderRefundsServiceImpl implements IDragonOrderRefundsService ...@@ -312,13 +314,13 @@ public class DragonOrderRefundsServiceImpl implements IDragonOrderRefundsService
// 创建退款日志 // 创建退款日志
mqHandleUtil.sendMySqlRedis( mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_order_refund_log.insert"), SqlMapping.get("dragon_order_refund_log.insert"),
new Object[]{orderRefundId, paymentType, data, nowTime, nowTime}, new Object[]{orderRefundId, paymentType, JSON.toJSONString(data), nowTime, nowTime},
DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode() DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
); );
try { try {
mqHandleUtil.sendMySqlRedis( mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_order_refund_success.update"), SqlMapping.get("dragon_order_refund_success.update"),
new Object[]{nowTime, null, DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode(), code}, new Object[]{nowTime, nowTime, DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode(), code},
DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode() DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
); );
} catch (Exception e) { } catch (Exception e) {
...@@ -752,10 +754,10 @@ public class DragonOrderRefundsServiceImpl implements IDragonOrderRefundsService ...@@ -752,10 +754,10 @@ public class DragonOrderRefundsServiceImpl implements IDragonOrderRefundsService
} }
//商户订单号 商户退款单号 //商户订单号 商户退款单号
dto.setOrderRefundCode(orderId); dto.setOrderRefundCode(orderId);
//银联无这个 //从redis里面
dto.setRefundCode(""); dto.setRefundCode(dataUtils.getOrderCode(orderId));
dto.setRefundPrice(new BigDecimal(notifyMap.get("settleAmt")).divide(BigDecimal.valueOf(100)).toString()); dto.setRefundPrice(new BigDecimal(notifyMap.get("settleAmt")).divide(BigDecimal.valueOf(100)).toString());
dto.setRefundAt(notifyMap.get("traceTime")); dto.setRefundAt(DateUtil.Formatter.yyyyMMddHHmmss.format(LocalDateTime.now()));
// 应答信息 // 应答信息
dto.setRefundError(notifyMap.get("respMsg")); dto.setRefundError(notifyMap.get("respMsg"));
log.info("SEND WEPAY NOTIFTURL = " + JSON.toJSONString(dto)); log.info("SEND WEPAY NOTIFTURL = " + JSON.toJSONString(dto));
...@@ -767,7 +769,7 @@ public class DragonOrderRefundsServiceImpl implements IDragonOrderRefundsService ...@@ -767,7 +769,7 @@ public class DragonOrderRefundsServiceImpl implements IDragonOrderRefundsService
); );
mqHandleUtil.sendMySqlRedis( mqHandleUtil.sendMySqlRedis(
SqlMapping.get("dragon_order_refund_success.update"), SqlMapping.get("dragon_order_refund_success.update"),
new Object[]{nowTime, notifyMap.get("traceTime"), DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode(), orderId}, new Object[]{nowTime, nowTime, DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode(), orderId},
DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode() DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
); );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment