package com.nuvole.hnnx.hnnxPay;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.csii.sg.codec.Hex;
import com.csii.sg.security.ValidationException;
import com.csii.sg.security.impl.Permutation;
import com.csii.sg.security.impl.SignatureVerifier;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nuvole.hnnx.conf.NxPayConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName HttpClientUtils
* @Author cy
* @Date 2023/9/27
* @Description
* @Version 1.0
**/
@Component
@Slf4j
//@ConditionalOnClass(name = "com.nuvole.hnnx.conf.NxPayConfig")
public class NXHttpClientUtils {
@Autowired
private PrivateKey nxPayPrivateKey;
@Autowired
private PrivateKey nxKjPayPrivateKey;
@Autowired
private PublicKey nxPayPublicKey;
@Autowired
private PublicKey nxKjPayPublicKey;
@Autowired
private NxPayConfig nxPayConfig;
private static SignatureSigner signable = new SignatureSigner();
private static SignatureVerifier verifier = new SignatureVerifier();
public String getPlatSubMerchantId() {
return nxPayConfig.getPlatSubMerchantId();
}
public String getKjPlatSubMerchantId() {
return nxPayConfig.getKjPlatSubMerchantId();
}
public String getBranchId() {
return nxPayConfig.getBranchId();
}
/**
* 分转为元
*
* @param payMoney
* @return
*/
public static BigDecimal convertToYuan(long payMoney) {
BigDecimal totalAmount = new BigDecimal("" + payMoney).divide(new BigDecimal("100"));
return totalAmount;
}
public static void writeToFile(String sign, String plainStr) {
File file = new File("D:\\dev_nginx-1.18.0\\html\\testNetPay4.html");
String content = "\n" +
"\n" +
"
\n" +
" \n" +
" Title\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n" +
"\n";
try (FileWriter writer = new FileWriter(file)) {
writer.write(content);
System.out.println("内容成功写入文件。");
} catch (IOException e) {
System.err.println("写入文件时发生错误:" + e.getMessage());
}
}
public static void writeToFile(String url) {
File file = new File("D:\\dev_nginx-1.18.0\\html\\redirect1.html");
String content = "\n" +
"\n" +
"\n" +
" \n" +
"\n" +
"\n" +
" 正在跳转,请稍等...
\n" +
"\n" +
"\n";
try (FileWriter writer = new FileWriter(file)) {
writer.write(content);
System.out.println("内容成功写入文件。");
} catch (IOException e) {
System.err.println("写入文件时发生错误:" + e.getMessage());
}
}
/**
* 加签方法
*
* @param headerMap 加密报文头
* @param payloadJson 加密报文体
* @return
*/
public String sign(Map headerMap, String payloadJson) {
log.info("----------- 签名开始 ----------- ");
log.info("请求参数payloadJson:{}", payloadJson);
ObjectMapper objectMapper = new ObjectMapper();
String palin = null;
try {
if (payloadJson != null) {
Map payloadMap = objectMapper.readValue(payloadJson, Map.class);
headerMap.putAll(payloadMap);
}
palin = Permutation.sort(headerMap, "UTF-8");
log.info("待签名字符串:{}", palin);
} catch (Exception e) {
e.printStackTrace();
}
String sign = signable.sign(palin, nxPayPrivateKey);
log.info("签名结果:{}", sign);
log.info("----------- 签名结束 ----------- ");
return sign;
}
public String kjSign(String palin) {
log.info("----------- 签名开始 ----------- ");
log.info("请求参数 palin:{}", palin);
String sign = signable.kjSign(palin, nxKjPayPrivateKey).replaceAll("\\s", "");
log.info("签名结果:{}", sign);
log.info("----------- 签名结束 ----------- ");
return sign;
}
// 回调通知校验
public boolean notifyRespVerify(String notifyParam) {
log.info("回调通知验签 body 为: {}", notifyParam);
int signIndex = notifyParam.lastIndexOf("&signature=");
if (signIndex == -1) {
return false;
}
String palin = notifyParam.substring(0, signIndex);
String sign = notifyParam.substring(signIndex).replace("&signature=", "");
boolean verfiy = false;
try {
verfiy = verifier.verify(HnnxConstant.ALGORITHM, palin.getBytes(), Hex.toByte(sign), nxPayPublicKey);
} catch (ValidationException e) {
e.printStackTrace();
}
if (verfiy) {
log.info("返回值验签 结果:{}", verfiy);
} else {
log.error("返回值验签 结果:{}", verfiy);
}
log.info("----------- 返回值验签 结束 ----------- ");
return verfiy;
}
public String sendForm(HttpRequest nxPayHttpClient, HashMap payLoadMap) {
log.info("transCode : {}", nxPayHttpClient.header("transCode"));
Map headerMap = nxPayConfig.getHeadMap(nxPayHttpClient.header("sequenceId"), nxPayHttpClient.header("timestamp"), nxPayHttpClient.header("branchId"));
HashMap formData = new HashMap<>();
formData.put("payload", JSONObject.toJSONString(payLoadMap));
// 及具体接口的请求报文构成。
log.info("请求头: {}", JSONObject.toJSONString(headerMap));
formData.put("signature", sign(headerMap, (String) formData.get("payload")));
log.info("请求参数: {}", JSONObject.toJSONString(formData));
HttpResponse httpResponse = nxPayHttpClient.form(formData).execute();
String body = httpResponse.body();
verify(body);
return body;
}
/**
* 预支付
* 可以实现用户到支付宝或微信的预支付功能。
*
* @param subMerchantId 二级商户号
* @param branchId 交易机构号
* @param merSeqNbr 商户总交易流水号
* @param transAmt 交易总金额
* @param timeStamp 商户交易时间
* @param channelNbr 渠道编号 01-O2O 02-B2C 03-扫码
* @param payTypCd B-支付宝扫码支付C-微信扫码支付D-银联扫码支付
* @param orderTitle 订单标题
*/
public String qrCodePrePay(String subMerchantId, String branchId, String operatorId, String merSeqNbr, String authCode, long transAmt, String timeStamp, String channelNbr, char payTypCd,
String merUrl, String orderTitle) {
log.info("----------------- 预支付 开始 订单号为: {},订单金额为:{}----------------- ", merSeqNbr, transAmt);
HttpRequest nxPayHttpClient = nxPayConfig.getPayCloseableHttpClient();
//请求序列号【渠道端产生,一笔业务的唯一标识,贯穿整个交易始终】渠道代码(2位)+日期(yyMMdd 6位)+流水号(24位,appCode+剩余位数流水号)
// String sequenceId = getSequenceId(timeStamp, nxPayConfig.getAppCode());
// nxPayHttpClient.header("sequenceId", sequenceId);
nxPayHttpClient.header("timestamp", timeStamp);
nxPayHttpClient.header("transCode", HnnxConstant.TRANS_CODE_QRCODEPREPAY_PAY);
nxPayHttpClient.header("branchId", branchId);
// 拼接业务数据
HashMap formData = new HashMap<>();
// 一级商户号
formData.put("MerNbr", nxPayConfig.getMerNbr());
// 二级商户编号
formData.put("SubMerchantId", subMerchantId);
//商户交易时间
formData.put("MerTransDateTime", timeStamp);
//交易总金额
formData.put("TransAmt", convertToYuan(transAmt));
formData.put("AuthCode", authCode);
//渠道编号 01-O2O 02-B2C 03-扫码
formData.put("ChannelNbr", channelNbr);
//支付方式 8-线上支付宝扫码支付9-线上微信扫码支付A-线上银联扫码支付B-线下支付宝扫码支付C-线下微信扫码支付D-线下银联扫码支付
formData.put("PayTypCd", payTypCd);
formData.put("OrderTitle", orderTitle);
formData.put("CurrencyCd", "CNY");
//异步通知Url
formData.put("MerUrl", merUrl);
//操作员
formData.put("OperatorId", operatorId);
//支付订单号
formData.put("MerSeqNbr", merSeqNbr);
String body = sendForm(nxPayHttpClient, formData);
log.info("----------------- 预支付 结束 ----------------- ");
return body;
}
/**
* 用户主动扫码生成
* 用户需要扫描商户收款码动码进行支付时,通过此接口生成商户收款码动码,生产上现在微信主扫动码已经停止使用。
*
* @param subMerchantId 二级商户号
* @param branchId 交易机构号
* @param merSeqNbr 商户总交易流水号
* @param transAmt 交易总金额
* @param timeStamp 商户交易时间
* @param channelNbr 渠道编号 01-O2O 02-B2C 03-扫码
* @param payTypCd B 支付宝扫码支付 C 微信扫码支付 D 银联扫码支付
* @param orderTitle 订单标题
*/
public String dyActiveQrCode(String subMerchantId, String branchId, String merSeqNbr, long transAmt, String timeStamp, String channelNbr, char payTypCd,
String merUrl, String orderTitle) {
log.info("----------------- 用户主动扫码生成 开始 订单号为: {},订单金额为:{}----------------- ", merSeqNbr, transAmt);
HttpRequest nxPayHttpClient = nxPayConfig.getPayCloseableHttpClient();
//请求序列号【渠道端产生,一笔业务的唯一标识,贯穿整个交易始终】渠道代码(2位)+日期(yyMMdd 6位)+流水号(24位,appCode+剩余位数流水号)
// String sequenceId = getSequenceId(timeStamp, nxPayConfig.getAppCode());
// nxPayHttpClient.header("sequenceId", sequenceId);
nxPayHttpClient.header("timestamp", timeStamp);
nxPayHttpClient.header("transCode", HnnxConstant.TRANS_CODE_DYACTIVEQRCODE_PAY);
nxPayHttpClient.header("branchId", branchId);
// 拼接业务数据
HashMap formData = new HashMap<>();
// 一级商户号
formData.put("MerNbr", nxPayConfig.getMerNbr());
//商户总交易流水号
formData.put("MerSeqNbr", merSeqNbr);
//交易总金额
formData.put("TransAmt", convertToYuan(transAmt));
//商户交易时间
formData.put("MerTransDateTime", timeStamp);
//渠道编号 01-O2O 02-B2C 03-扫码
formData.put("ChannelNbr", channelNbr);
formData.put("CurrencyCd", "CNY");
//支付方式 B 支付宝扫码支付 C 微信扫码支付 D 银联扫码支付
formData.put("PayTypCd", payTypCd);
// 二级商户编号
formData.put("SubMerchantId", subMerchantId);
//异步通知Url
formData.put("MerUrl", merUrl);
formData.put("OrderTitle", orderTitle);
String body = sendForm(nxPayHttpClient, formData);
log.info("----------------- 用户主动扫码生成 结束 ----------------- ");
return body;
}
/**
* 用户被扫支付
* 第三方平台扫描用户付款码,通过此接口提交支付
*/
public String coretoall(String subMerchantId, String branchId, String merSeqNbr, long transAmt, String payAuthCode, String timeStamp, String channelNbr,
String merUrl, String orderTitle, String terminalCode) {
log.info("----------------- 用户被扫支付 开始, 订单编号= {} ,订单金额为:{}----------------- ", merSeqNbr, transAmt);
HttpRequest nxPayHttpClient = nxPayConfig.getPayCloseableHttpClient();
nxPayHttpClient.header("timestamp", timeStamp);
nxPayHttpClient.header("transCode", HnnxConstant.TRANS_CODE_CORETOALL_PAY);
nxPayHttpClient.header("branchId", branchId);
// 拼接业务数据
HashMap formData = new HashMap<>();
// 一级商户号
formData.put("MerNbr", nxPayConfig.getMerNbr());
//商户总交易流水号
formData.put("MerSeqNbr", merSeqNbr);
//交易总金额
formData.put("TransAmt", convertToYuan(transAmt));
//商户交易时间
formData.put("MerTransDateTime", timeStamp);
//二维码
formData.put("QrCodeInfo", payAuthCode);
//渠道编号 01-O2O 02-B2C 03-扫码
formData.put("ChannelNbr", channelNbr);
formData.put("CurrencyCd", HnnxConstant.CURRENCYCD);
formData.put("AreaInfo", HnnxConstant.AREAINFO);
// 二级商户编号
formData.put("SubMerchantId", subMerchantId);
//订单详情
formData.put("OrderTitle", orderTitle);
//异步通知Url
formData.put("MerUrl", merUrl);
//商户终端设备类型
formData.put("TerminalType", "04");
//终端编号 由柜员在后管添加终端时生成
formData.put("Equipid", "002000156");
//终端序列号
formData.put("Equipseqnbr", "000002041170132246");
formData.put("Lgtude", "113.988007");
formData.put("Lttude", "34.819642");
formData.put("AppVersion", "01234567");
String body = sendForm(nxPayHttpClient, formData);
log.info("----------------- 用户被扫支付 结束 ----------------- ");
return body;
}
/**
* 订单交易状态查询
* 接口说明
* 该接口提供支付、退款交易的交易状态查询。
* 根据交易状态TransStatus确定交易结果;
* 微信退款交易状态查询,非银行卡交易一般在15秒内可查询交易成功,银行卡交易退款需在两分钟后可查询到交易成功。
*
* @param merSeqNbr 订单流水号
* @return
* @throws Exception
*/
public String qryQrOrderStatus(String merSeqNbr, String branchId) {
log.info("----------------- 订单交易状态查询 开始----------------- ");
HttpRequest nxPayHttpClient = nxPayConfig.getPayCloseableHttpClient();
String timeStamp = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN);
//请求序列号【渠道端产生,一笔业务的唯一标识,贯穿整个交易始终】渠道代码(2位)+日期(yyMMdd 6位)+流水号(24位,appCode+剩余位数流水号)
// String sequenceId = getSequenceId(timeStamp, nxPayConfig.getAppCode());
// nxPayHttpClient.header("sequenceId", sequenceId);
nxPayHttpClient.header("timestamp", timeStamp);
nxPayHttpClient.header("transCode", HnnxConstant.TRANS_CODE_QRYQRORDERSTATUS_PAY);
nxPayHttpClient.header("branchId", branchId);
// 拼接业务数据
HashMap formData = new HashMap<>();
// 一级商户号
formData.put("MerNbr", nxPayConfig.getMerNbr());
//商户总交易流水号
formData.put("MerSeqNbr", merSeqNbr);
String body = sendForm(nxPayHttpClient, formData);
log.info("----------------- 订单交易状态查询 结束 ----------------- ");
return body;
}
/**
* 退款
*
* @param subMerchantId 原支付交易二级商户号
* @param branchId
* @param merSeqNbr 要退款的订单号
* @param merSeqDate 要退款的订单交易日期 例:20190810
* @param origTransAmt 要退款的订单的交易金额
* @param transAmt 退款金额
* @param timeStamp 当前日期 例:yyyyMMddHHmmss
* @return
*/
public String returntrans(String subMerchantId, String branchId, String merSeqNbr, String merSeqDate, long origTransAmt,
long transAmt, String timeStamp) {
log.info("----------------- 退款 开始----------------- ");
HttpRequest nxPayHttpClient = nxPayConfig.getPayCloseableHttpClient();
nxPayHttpClient.header("timestamp", timeStamp);
nxPayHttpClient.header("transCode", HnnxConstant.TRANS_CODE_RETURNTRANS_PAY);
nxPayHttpClient.header("branchId", branchId);
// 拼接业务数据
HashMap formData = new HashMap<>();
// 一级商户号
formData.put("MerNbr", nxPayConfig.getMerNbr());
//商户总交易流水号
formData.put("MerSeqNbr", "TK_" + merSeqNbr);
//退货交易时间
formData.put("MerTransDateTime", timeStamp);
//原商户流水
formData.put("OrigMerSeqNbr", merSeqNbr);
//原商户日期
formData.put("OrigMerDate", merSeqDate);
//原支付交易金额
formData.put("OrigTransAmt", convertToYuan(origTransAmt));
//二级商户号
formData.put("SubMerchantId", subMerchantId);
//退货二级商户流水号(随机生成,不允许出现重复,可以和一级商户交易流水号保持一致)
formData.put("SubMerSeqNo", "TK_" + merSeqNbr);
//二级商户时间
formData.put("SubMerDateTime", timeStamp);
//二级商户退货交易退货金额
formData.put("SubTransAmt", convertToYuan(transAmt));
//原二级商户支付流水号(与原支付交易一级商户号流水号一致)
formData.put("OrigSubMerSeqNo", merSeqNbr);
//原二级商户支付交易日期(例:20190810)
formData.put("OrigSubMerDate", merSeqDate);
//订单号 与二级商户流水号保持一致
formData.put("OrderNbr", merSeqNbr);
String body = sendForm(nxPayHttpClient, formData);
log.info("----------------- 退款 结束----------------- ");
return body;
}
/**
* 对账查询
* String subMerchantId, String branchId,
*
* @param clearDate 对账日期 YYYY-MM-DD
* @param branchId 交易机构号
* @return
*/
public String accountqry(String clearDate, String branchId) {
log.info("----------------- 对帐 开始----------------- ");
HttpRequest nxPayHttpClient = nxPayConfig.getPayCloseableHttpClient();
nxPayHttpClient.header("timestamp", DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN));
nxPayHttpClient.header("transCode", HnnxConstant.TRANS_CODE_ACCOUNTQRY_PAY);
nxPayHttpClient.header("branchId", branchId);
// 拼接业务数据
HashMap formData = new HashMap<>();
formData.put("ClearDate", clearDate);
String body = sendForm(nxPayHttpClient, formData);
log.info("----------------- 对帐 结束----------------- ");
return body;
}
// 订单号生成规则 “渠道简称-订单号-主/优惠-发起支付次数”构成
// 例如商圈的主订单第一次发起支付,订单号就是“SQ-商圈订单id-Z-1”
// 如果这个订单关联有优惠金,优惠金订单号就是"SQ-商圈订单id-Y-1"
public static String getNxPayOrderId(String prefix, long orderId, char orderType, short tryNum) {
return new StringBuilder(prefix).append("-").append(orderId).append("-").append(orderType).append("-").append(tryNum).toString();
}
/**
* 验签
*
* @return
*/
public boolean verify(String body) {
log.info("返回值验签 body 为: {}", body);
log.info("----------- 返回值验签 开始 ----------- ");
boolean verfiy = false;
try {
Map bodyMap = JSON.parseObject(body, Feature.OrderedField);
String sign = (String) bodyMap.remove("signature");
String payload = (String) bodyMap.remove("payload");
ObjectMapper objectMapper = new ObjectMapper();
if (payload != null) {
Map payloadMap = objectMapper.readValue(payload, Map.class);
bodyMap.putAll(payloadMap);
}
String palin = null;
palin = Permutation.sort(bodyMap, "UTF-8");
log.info("排序后的字符串:{}", palin);
if (StrUtil.isNotEmpty(sign)) {
verfiy = verifier.verify(HnnxConstant.ALGORITHM, palin.getBytes(), Hex.toByte(sign), nxPayPublicKey);
}
} catch (Exception e) {
e.printStackTrace();
}
log.error("返回值验签 结果:{}", verfiy);
log.info("----------- 返回值验签 结束 ----------- ");
return verfiy;
}
public boolean kjVerify(String sign, String palin) {
log.info("返回值验签 palin 为: {}", palin);
log.info("返回值验签 sign 为: {}", sign);
log.info("----------- 返回值验签 开始 ----------- ");
boolean verfiy = false;
try {
if (StrUtil.isNotEmpty(sign)) {
verfiy = verifier.verify(HnnxConstant.KJ_ALGORITHM, palin.getBytes(), Base64.getDecoder().decode(sign), nxKjPayPublicKey);
}
} catch (Exception e) {
e.printStackTrace();
}
log.error("返回值验签 结果:{}", verfiy);
log.info("----------- 返回值验签 结束 ----------- ");
return verfiy;
}
/**
* 通用快捷支付
*
* @param merSeqNbr 商户流水号
* @param subMerchantId 二级商户号
* @param backURL 后台通知URL
* @param frontURL 返回前端URL
*/
public String quickPayRequest(String subMerchantId, String merSeqNbr, long transAmt, String nowTime,
String frontURL, String backURL, String orderTitle) {
log.info("----------------- 通用快捷支付 开始, 订单编号= {} ,订单金额为:{}----------------- ", merSeqNbr, transAmt);
// 拼接业务数据
JSONObject formData = new JSONObject();
formData.put("deviceType", "5");
HashMap plainData = new HashMap<>();
// plain 开始
//一级商户id
// plainData.put("merchId", "010020170801000001");
plainData.put("merchId", nxPayConfig.getKjMerNbr());
//优惠前金额 disCountAmt
//订单名称 orderName
plainData.put("orderName", orderTitle);
//币种 ccy
plainData.put("ccy", "01");
//返回前端URL frontURL
plainData.put("frontURL", frontURL);
//后台通知URL backURL
plainData.put("backURL", backURL);
//订单备注 orderRemark
plainData.put("orderRemark", "");
//渠道号 channelNbr
plainData.put("channelNbr", "02");
//交易总金额 txnAmt
plainData.put("txnAmt", convertToYuan(transAmt));
//商户流水号 merSeqNbr
plainData.put("merSeqNbr", merSeqNbr);
//交易时间 orderTime
plainData.put("orderTime", nowTime);
//收款方名称 payee
//优惠活动名称 specialOffers
//商户订单号 merchOrderId
plainData.put("merchOrderId", merSeqNbr);
JSONArray plainMerTrans = new JSONArray();
JSONObject plainMerTransData1 = new JSONObject();
//子交易金额
plainMerTransData1.put("subTransAmt", convertToYuan(transAmt));
//二级商户号
plainMerTransData1.put("subMerchantId", subMerchantId);
//二级商户交易时间 subMerDateTime
plainMerTransData1.put("subMerDateTime", nowTime);
//子流水号 subMerSeqNo
plainMerTransData1.put("subMerSeqNo", merSeqNbr);
//二级商户名称 subMerchantName
plainMerTransData1.put("subMerchantName", "");
//二级商户商品信息 productInfo
plainMerTransData1.put("productInfo", "");
//二级商户信息 subMerImport
// plainMerTransData1.put("subMerImport", "学费");
// plainMerTransData1.put("subMerImport", orderTitle);
//卡券号 platCouponId
plainMerTransData1.put("platCouponId", "");
//子卡券交易金额 platCouponAmount
plainMerTransData1.put("platCouponAmount", "");
//子积分数 bonusPoint
plainMerTransData1.put("bonusPoint", "");
//子积分交易金额 bonusPointAmount
plainMerTransData1.put("bonusPointAmount", "");
// plainMerTransData1.put("subInteralAmt", "0.01");
// plainMerTransData1.put("subCouponAmt", "");
plainMerTrans.add(plainMerTransData1);
plainData.put("MerTransList", plainMerTrans);
String plainStr = JSONObject.toJSONString(plainData);
log.info("请求参数:{}", plainStr);
// formData.put("plain", plainData);
formData.put("plain", plainStr);
// plain 结束
// 开始签名
String signature = kjSign(plainStr);
formData.put("signature", signature);
// writeToFile(signature, plainStr);
HttpResponse httpResponse = HttpRequest.post(nxPayConfig.getKjUrl() + HnnxConstant.QUICK_PAY_URL)
.contentType("application/x-www-form-urlencoded;")
.form(formData.getInnerMap())
.timeout(20000)//超时,毫秒
.execute();
String location = null;
log.info("----------------- 通用快捷支付 结束 ----------------- ");
if (httpResponse.getStatus() == 302) {
location = httpResponse.header("Location");
// writeToFile(location);
return location;
}else {
throw new RuntimeException(httpResponse.body());
}
}
/**
* 快捷支付 订单状态查询
*
* @param orderNbr 订单编号
* @param startDate 起始日期 yyyyMMdd
* @param endDate 结束日期 yyyyMMdd
* @param pageSize 每页记录数
* @param pageNum 当前第几页
* @return
*/
public String quickPayOrderQueryRequest(String orderNbr, String startDate, String endDate, int pageSize, int pageNum) {
log.info("----------------- 快捷支付订单交易状态查询 开始----------------- ");
String body = null;
JSONObject formData = new JSONObject();
formData.put("MerNbr", nxPayConfig.getKjMerNbr());
//订单编号
if (StrUtil.isNotEmpty(orderNbr)) {
formData.put("OrderNbr", orderNbr);
}
//起始日期
if (StrUtil.isNotEmpty(orderNbr)) {
formData.put("StartDate", startDate);
}
//结束日期
if (StrUtil.isNotEmpty(orderNbr)) {
formData.put("EndDate", endDate);
}
//每页记录数
formData.put("PageSize", pageSize);
//当前第几页
formData.put("PageNum", pageNum);
log.info("快捷支付订单查询参数:{}", formData);
body = HttpRequest.post(nxPayConfig.getKjUrl() + HnnxConstant.QUICK_PAY_QUERY_URL)
.contentType("application/x-www-form-urlencoded;")
.form(formData.getInnerMap())
.timeout(20000)//超时,毫秒
.execute().body();
log.info("快捷支付订单查询请求结果:{}", body);
log.info("----------------- 快捷支付订单交易状态查询 结束 ----------------- ");
return body;
}
/**
* 退款
*
* @param subMerchantId 原支付交易二级商户号
* @param merSeqNbr 要退款的订单号
* @param merSeqDate 要退款的订单交易日期 yyyyMMdd 例:20190810
* @param origTransAmt 要退款的订单的交易金额
* @param transAmt 退款金额
* @param timeStamp 当前日期 例:yyyyMMddHHmmss
* @return
*/
public String quickPayReturntrans(String subMerchantId, String merSeqNbr, String merSeqDate, long origTransAmt,
long transAmt, String timeStamp) {
log.info("----------------- 退款 开始----------------- ");
String timeStampWithSpace = timeStamp.substring(0, 8) + " " + timeStamp.substring(8);
// 拼接业务数据
HashMap formData = new HashMap<>();
// 一级商户号
formData.put("MerNbr", nxPayConfig.getKjMerNbr());
//商户总交易流水号
formData.put("MerSeqNbr", "TK_" + merSeqNbr);
//退货交易时间 yyyyMMdd HHmmss 差异!!!!
formData.put("MerTransDateTime", timeStampWithSpace);
// formData.put("MerTransDateTime", timeStamp);
//原商户流水
formData.put("OrigMerSeqNbr", merSeqNbr);
//原商户日期
formData.put("OrigMerDate", merSeqDate);
//原支付交易金额
formData.put("OrigTransAmt", convertToYuan(origTransAmt));
//二级商户号
formData.put("SubMerchantId", subMerchantId);
//退货二级商户流水号(随机生成,不允许出现重复,可以和一级商户交易流水号保持一致)
formData.put("SubMerSeqNo", "TK_" + merSeqNbr);
//二级商户时间
formData.put("SubMerDateTime", timeStampWithSpace);
// formData.put("SubMerDateTime", timeStamp);
//二级商户退货交易退货金额
formData.put("SubTransAmt", convertToYuan(transAmt));
//原二级商户支付流水号(与原支付交易一级商户号流水号一致)
formData.put("OrigSubMerSeqNo", merSeqNbr);
//原二级商户支付交易日期(例:20190810)
formData.put("OrigSubMerDate", merSeqDate);
//订单号 与二级商户流水号保持一致
formData.put("OrderNbr", merSeqNbr);
log.info("快捷支付订单退款参数:{}", formData);
String body = null;
HttpResponse httpResponse = HttpRequest.post(nxPayConfig.getKjUrl() + HnnxConstant.QUICK_PAY_RETURN_URL)
.contentType("application/x-www-form-urlencoded;")
.form(formData)
.timeout(20000)//超时,毫秒
.execute();
body = httpResponse.body();
log.info(" 快捷支付退款结果:{}", body);
log.info("----------------- 退款 结束----------------- ");
return body;
}
}