You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1240 lines
49 KiB
1240 lines
49 KiB
package com.ynxbd.wx.wxfactory;
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.ynxbd.common.bean.enums.MerchantEnum;
|
|
import com.ynxbd.common.bean.pay.Bill;
|
|
import com.ynxbd.common.bean.pay.Order;
|
|
import com.ynxbd.common.helper.cache.TextCache;
|
|
import com.ynxbd.common.helper.common.*;
|
|
import com.ynxbd.common.result.ResultEnum;
|
|
import com.ynxbd.common.result.ServiceException;
|
|
import com.ynxbd.wx.config.WeChatConfig;
|
|
import com.ynxbd.wx.wxfactory.bean.WxPayNotify;
|
|
import com.ynxbd.wx.wxfactory.bean.refund.WxRefundItem;
|
|
import com.ynxbd.wx.wxfactory.bean.refund.WxRefundQueryRoot;
|
|
import com.ynxbd.wx.wxfactory.utils.WxSignHelper;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.apache.commons.lang3.ObjectUtils;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import weixin.popular.api.PayMchAPI;
|
|
import weixin.popular.bean.paymch.*;
|
|
import weixin.popular.client.LocalHttpClient;
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import java.math.BigDecimal;
|
|
import java.util.*;
|
|
import java.util.stream.Collectors;
|
|
|
|
import static weixin.popular.api.PayMchAPI.payRefundquery;
|
|
|
|
/**
|
|
* @Author wsq
|
|
* @Date 2020/8/17 15:26
|
|
* @Copyright @ 2020 云南新八达科技有限公司 All rights reserved.
|
|
*/
|
|
@Slf4j
|
|
public class WxPayHelper {
|
|
// 证书名称
|
|
public static final String API_CLIENT_CERT_NAME = "apiclient_cert.p12";
|
|
public static final String ALL = "ALL"; // 查询全部订单
|
|
|
|
// 交易成功返回内容
|
|
public static final String REVOKED = "REVOKED"; // 订单已撤销
|
|
public static final String PAY_ERROR = "PAYERROR"; // 支付失败
|
|
public static final String USER_PAYING = "USERPAYING"; // 用户支付中
|
|
public static final String REFUND = "REFUND"; // 发生过退款
|
|
|
|
// 失败
|
|
public static final String FAIL = "FAIL";
|
|
|
|
// 成功
|
|
public static final String SUCCESS = "SUCCESS";
|
|
public static final String OK = "OK";
|
|
// 排重
|
|
public static final RepeatKeyHelper KEYS = new RepeatKeyHelper(60);
|
|
|
|
static {
|
|
try {
|
|
String mchId = WeChatConfig.MCH_ID;
|
|
if (!ObjectUtils.isEmpty(mchId)) {
|
|
String clazzPath = Objects.requireNonNull(WxPayHelper.class.getClassLoader().getResource("")).getPath();
|
|
if (clazzPath == null) {
|
|
log.info("【微信】未找到证书");
|
|
}
|
|
LocalHttpClient.initMchKeyStore(mchId, clazzPath + API_CLIENT_CERT_NAME);
|
|
}
|
|
} catch (Exception e) {
|
|
ErrorHelper.println(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 微信支付调用及通知
|
|
*
|
|
* @param request 请求
|
|
* @return 微信支付信息
|
|
*/
|
|
public static WxPayNotify payNotify(HttpServletRequest request) throws ServiceException {
|
|
try {
|
|
// 转换数据对象
|
|
Map<String, Object> paramsMap = WxSignHelper.getReqXmlParamsMap(request);
|
|
log.info("【微信回调】map={}", paramsMap);
|
|
if (paramsMap == null) {
|
|
throw new ServiceException("【微信】回调通知下单信息返回错误");
|
|
}
|
|
|
|
// 签名验证
|
|
if (!WxSignHelper.validateSign(paramsMap, WeChatConfig.MCH_KEY)) { // 验证未通过,通知支付失败
|
|
throw new ServiceException("【微信】回调通知签名验证未通过!");
|
|
}
|
|
|
|
String json = JsonHelper.toJsonString(paramsMap);
|
|
if ("".equals(json)) {
|
|
throw new ServiceException("【微信】回调通知下单信息为空");
|
|
}
|
|
|
|
WxPayNotify notifyInfo = JsonHelper.parseObject(json, WxPayNotify.class);
|
|
log.info("【微信回调】notifyInfo={}", notifyInfo);
|
|
if (notifyInfo == null) {
|
|
throw new ServiceException("【微信】回调通知下单信息转换失败");
|
|
}
|
|
|
|
String openid = notifyInfo.getOpenid();
|
|
String outTradeNo = notifyInfo.getOutTradeNo();
|
|
String bankTransNo = notifyInfo.getTransactionId();
|
|
BigDecimal totalFee = notifyInfo.getTotalFee();// 金额
|
|
String timeEnd = notifyInfo.getTimeEnd();
|
|
|
|
if (openid == null || outTradeNo == null || bankTransNo == null || totalFee == null || timeEnd == null) {
|
|
throw new ServiceException(String.format("【微信】下单信息返回错误 outTradeNo={%s}", outTradeNo));
|
|
}
|
|
|
|
// 已处理 去重
|
|
if (KEYS.isContainsKey(bankTransNo)) {
|
|
throw new ServiceException(ResultEnum.PAY_NOTIFY_REPEAT, String.format("【微信】[重复请求]下单信息去重 outTradeNo={%s}", outTradeNo));
|
|
}
|
|
|
|
String info = WxSignHelper.getMapInfo(paramsMap);
|
|
|
|
Map<String, String> dateMap = WxSignHelper.getDateMap(timeEnd);
|
|
notifyInfo.setPayDate(dateMap.get(WxSignHelper.DATE_KEY));
|
|
notifyInfo.setPayTime(dateMap.get(WxSignHelper.TIME_KEY));
|
|
|
|
notifyInfo.setPayInfo(info);
|
|
notifyInfo.setTotalFee(totalFee.movePointLeft(2));
|
|
return notifyInfo;
|
|
} catch (Exception e) {
|
|
if (e instanceof ServiceException) {
|
|
throw e;
|
|
}
|
|
ErrorHelper.println(e);
|
|
throw new ServiceException(String.format("【微信】支付通知异常:[%s]", e.getMessage()));
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* 商户创建订单
|
|
*
|
|
* @param merchantEnum 枚举
|
|
* @param title 商品标题
|
|
* @param totalFee 订单金额
|
|
* @param outTradeNo 订单号
|
|
* @param notifyType 回调类型
|
|
* @param ip ip地址
|
|
* @param openid openid
|
|
* @param patientId 患者id
|
|
* @return 成功返回 json, 否则返回null
|
|
*/
|
|
public static JSONObject createOrder(MerchantEnum merchantEnum, String title, String totalFee, String outTradeNo, String notifyType, String ip, String openid, String patientId) {
|
|
try {
|
|
if (ObjectUtils.isEmpty(openid) || ObjectUtils.isEmpty(outTradeNo)
|
|
|| merchantEnum == null || totalFee == null || notifyType == null) {
|
|
log.info("【微信】下单参数缺失");
|
|
return null;
|
|
}
|
|
|
|
// 金额转换
|
|
String cents;
|
|
try {
|
|
cents = new BigDecimal(totalFee).movePointRight(2).toString(); // 单位分
|
|
} catch (Exception e) {
|
|
ErrorHelper.println(e);
|
|
log.info("【微信】统一下单金额转换异常");
|
|
return null;
|
|
}
|
|
|
|
String appId = WeChatConfig.APP_ID;
|
|
String mchId = WeChatConfig.MCH_ID;
|
|
String mchKey = WeChatConfig.MCH_KEY;
|
|
String nonce = UUID.randomUUID().toString().replace("-", "");
|
|
|
|
Unifiedorder unifiedorder = new Unifiedorder();
|
|
unifiedorder.setAppid(appId);
|
|
unifiedorder.setMch_id(mchId);
|
|
unifiedorder.setNonce_str(nonce);
|
|
unifiedorder.setOpenid(openid);
|
|
unifiedorder.setOut_trade_no(outTradeNo);
|
|
unifiedorder.setBody(title);
|
|
|
|
unifiedorder.setTotal_fee(cents); // 金额分
|
|
unifiedorder.setSpbill_create_ip(ip);
|
|
unifiedorder.setNotify_url(WeChatConfig.getBaseUrl() + merchantEnum.NOTIFY_URL);
|
|
unifiedorder.setTrade_type("JSAPI");
|
|
// 额外参数
|
|
unifiedorder.setAttach(notifyType);
|
|
|
|
log.info(appId + ","
|
|
+ mchId + ","
|
|
+ nonce + ","
|
|
+ title + ","
|
|
+ outTradeNo + ","
|
|
+ totalFee + ","
|
|
+ ip + ","
|
|
+ merchantEnum.NOTIFY_URL);
|
|
|
|
// 微信统一下单
|
|
UnifiedorderResult unifiedorderResult = PayMchAPI.payUnifiedorder(unifiedorder, mchKey);
|
|
log.info("【微信】统一下单返回:{}", JsonHelper.toJsonString(unifiedorderResult));
|
|
if (unifiedorderResult == null) {
|
|
log.info("【微信】统一下单失败");
|
|
return null;
|
|
}
|
|
|
|
String result_code = unifiedorderResult.getResult_code();
|
|
// 下单是否成功
|
|
Boolean sign_status = unifiedorderResult.getSign_status();
|
|
if (!SUCCESS.equals(result_code) || sign_status == null || !sign_status) {
|
|
log.info("【微信】统一下单返回异常信息:sign_status={}, err_code=[ {} ], err_code_des=[ {} ]", sign_status, unifiedorderResult.getErr_code(), unifiedorderResult.getErr_code_des());
|
|
return null;
|
|
}
|
|
String json = weixin.popular.util.PayUtil.generateMchPayJsRequestJson(unifiedorderResult.getPrepay_id(), appId, mchKey);
|
|
if (json != null) {
|
|
return JsonHelper.parseObject(json);
|
|
}
|
|
} catch (Exception e) {
|
|
log.error("【微信】统一下单异常信息:" + e.getMessage());
|
|
ErrorHelper.println(e);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
/**
|
|
* 微信退款
|
|
*
|
|
* @param outTradeNo 订单号
|
|
* @param outRefundNo 退款订单号(HIS订单号)
|
|
* @param refundMoney 本次退款金额
|
|
* @param totalFee 订单总金额
|
|
* @param desc 退款描述
|
|
* @return 退款信息
|
|
*/
|
|
public static Order refund(String outTradeNo, String outRefundNo, BigDecimal refundMoney, BigDecimal totalFee, String desc) {
|
|
Order order = new Order();
|
|
try {
|
|
int feeCents;
|
|
int totalFeeCents;
|
|
|
|
feeCents = refundMoney.movePointRight(2).intValue(); // 单位分
|
|
totalFeeCents = totalFee.movePointRight(2).intValue();
|
|
|
|
if (feeCents == 0 || totalFeeCents == 0) {
|
|
order.setErrorMsg(ResultEnum.REFUND_MONEY_IS_ZERO.message);
|
|
return order;
|
|
}
|
|
|
|
log.info("【微信】退款开始 outTradeNo={}, refundMoney={}, totalFee={}", outTradeNo, feeCents, totalFeeCents);
|
|
|
|
SecapiPayRefund refund = new SecapiPayRefund();
|
|
refund.setAppid(WeChatConfig.APP_ID);
|
|
refund.setMch_id(WeChatConfig.MCH_ID);
|
|
refund.setNonce_str(UUID.randomUUID().toString().replace("-", ""));
|
|
refund.setSign_type("MD5");
|
|
refund.setOut_trade_no(outTradeNo);
|
|
refund.setOut_refund_no(outRefundNo);
|
|
refund.setRefund_fee(feeCents);
|
|
refund.setTotal_fee(totalFeeCents);
|
|
refund.setRefund_fee_type("CNY");
|
|
refund.setRefund_account("REFUND_SOURCE_UNSETTLED_FUNDS");
|
|
if (desc.length() > 80) {
|
|
desc = desc.substring(0, 80);
|
|
}
|
|
|
|
desc = TextCache.textFilter(desc);
|
|
refund.setRefund_desc(desc);
|
|
|
|
SecapiPayRefundResult refundResult;
|
|
try {
|
|
refundResult = PayMchAPI.secapiPayRefund(refund, WeChatConfig.MCH_KEY);
|
|
if (refundResult == null) {
|
|
throw new Exception(ResultEnum.INTERFACE_WX_INVOKE_ERROR.message);
|
|
}
|
|
} catch (Exception e) {
|
|
log.error("【微信】退款接口调用异常 outTradeNo={}", outTradeNo);
|
|
order.setErrorMsg(ResultEnum.INTERFACE_WX_INVOKE_ERROR.message);
|
|
return order;
|
|
}
|
|
|
|
String code = refundResult.getReturn_code();
|
|
String message = refundResult.getReturn_msg();
|
|
String resultCode = refundResult.getResult_code();
|
|
if (!SUCCESS.equals(resultCode)) {
|
|
String errCode = refundResult.getErr_code();
|
|
String errCodeDesc = refundResult.getErr_code_des();
|
|
|
|
log.info("【微信】退款失败 code={}, message={}, resultCode={}, errCode={}, errCodeDesc={}", code, message, resultCode, errCode, errCodeDesc);
|
|
|
|
order.setErrorMsg(errCodeDesc);
|
|
order.setRefundResult(errCodeDesc); // 退款失败信息记录
|
|
return order;
|
|
}
|
|
|
|
log.info("【微信】退款返回 code={}, message={}, resultCode={}", code, message, resultCode);
|
|
order.setRefundResult(message); // 退款信息记录
|
|
if (!OK.equals(message)) { // 退款失败
|
|
order.setErrorMsg(ResultEnum.INTERFACE_WX_INVOKE_ERROR.message);
|
|
return order;
|
|
}
|
|
order.setSuccess(true);
|
|
return order;
|
|
} catch (Exception e) {
|
|
ErrorHelper.println(e);
|
|
order.setErrorMsg(ResultEnum.INTERFACE_WX_INVOKE_ERROR.message);
|
|
String refundResult = order.getRefundResult();
|
|
order.setRefundResult(ObjectUtils.isEmpty(refundResult) ? order.getErrorMsg() : refundResult);
|
|
return order;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* 微信扫码盒子支付
|
|
*
|
|
* @param title 商品标题
|
|
* @param outTradeNo 商户订单号
|
|
* @param totalFee 总金额
|
|
* @param authCode 微信条码
|
|
* @param ip ip地址
|
|
* @return 执行返回
|
|
*/
|
|
public static Order payMicro(String title, String outTradeNo, BigDecimal totalFee, String authCode, String ip) {
|
|
Order order = new Order();
|
|
|
|
if (StringUtils.isEmpty(outTradeNo) || StringUtils.isEmpty(authCode) || ip == null || totalFee == null) {
|
|
order.setErrorMsg("【微信】[盒子支付] 参数缺失");
|
|
return order;
|
|
}
|
|
|
|
int totalFeeCents;
|
|
try {
|
|
totalFeeCents = totalFee.movePointRight(2).intValue();
|
|
|
|
String appId = WeChatConfig.APP_ID;
|
|
String mchId = WeChatConfig.MCH_ID;
|
|
String mchKey = WeChatConfig.MCH_KEY;
|
|
String nonce = UUID.randomUUID().toString().replace("-", "");
|
|
|
|
Micropay micropay = new Micropay();
|
|
micropay.setAppid(appId);
|
|
micropay.setMch_id(mchId);
|
|
micropay.setNonce_str(nonce); // 随机字符串
|
|
micropay.setOut_trade_no(outTradeNo); // 商户订单号
|
|
micropay.setBody(title);
|
|
micropay.setAuth_code(authCode);
|
|
micropay.setTotal_fee(totalFeeCents); // 金额分
|
|
micropay.setSpbill_create_ip(ip);
|
|
|
|
// micropay.setDetail("描述"); // 商品描述
|
|
|
|
MicropayResult micropayResult = PayMchAPI.payMicropay(micropay, mchKey);
|
|
if (micropayResult == null) {
|
|
order.setErrorMsg("【微信】盒子扫码支付请求失败");
|
|
return order;
|
|
}
|
|
|
|
log.info("【微信】[盒子支付]支付反馈 {}", JsonHelper.toJsonString(micropayResult));
|
|
|
|
String openid = micropayResult.getOpenid();
|
|
String bankTransNo = micropayResult.getTransaction_id(); // 银行流水号
|
|
String resultCode = micropayResult.getResult_code();
|
|
String errMsg = micropayResult.getErr_code_des();
|
|
String errCode = micropayResult.getErr_code();
|
|
|
|
order.setOpenid(openid);
|
|
order.setBankTransNo(bankTransNo);
|
|
|
|
// 调用失败
|
|
if (FAIL.equals(micropayResult.getReturn_code())) { // 失败
|
|
log.info("【微信】[盒子支付]失败 outTradeNo={}, bankTransNo={}, returnCode={}, returnMsg={}", outTradeNo, bankTransNo, micropayResult.getReturn_code(), micropayResult.getReturn_msg());
|
|
order.setErrorCode(micropayResult.getReturn_code());
|
|
order.setErrorMsg(micropayResult.getReturn_msg());
|
|
return order;
|
|
}
|
|
|
|
Order wxOrder;
|
|
if (FAIL.equals(resultCode)) { // 失败
|
|
if (USER_PAYING.equals(errCode)) { // 密码支付
|
|
log.info("【微信】[盒子支付]密码支付 outTradeNo={}, msg={}", outTradeNo, errMsg);
|
|
for (int i = 1; i <= 5; i++) {
|
|
try {
|
|
Thread.sleep(5000 + ((i - 1) * 1500)); // 总共35s
|
|
wxOrder = queryOrder(outTradeNo);
|
|
if (wxOrder.isSuccess()) {
|
|
return wxOrder;
|
|
}
|
|
|
|
// 支付失败
|
|
if (PAY_ERROR.equals(wxOrder.getTradeState())) {
|
|
if (i == 1 || i == 2) {
|
|
Thread.sleep(i == 2 ? 3000 : 9000); // 等够15s
|
|
}
|
|
|
|
// 撤销订单
|
|
Order cancelOrder = cancelOrder(wxOrder.getOutTradeNo(), wxOrder.getBankTransNo());
|
|
// 撤销成功
|
|
if (cancelOrder.isSuccess()) {
|
|
wxOrder.setTradeState(REVOKED);
|
|
wxOrder.setErrorMsg("订单已撤销");
|
|
}
|
|
return wxOrder;
|
|
}
|
|
|
|
// 其他失败原因
|
|
if (!USER_PAYING.equals(wxOrder.getTradeState())) {
|
|
return wxOrder;
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
} else {
|
|
order.setErrorCode(errCode);
|
|
order.setErrorMsg(errMsg);
|
|
log.info("【微信】[盒子支付]失败 outTradeNo={}, bankTransNo={}, errCode={}, errMsg={}", outTradeNo, bankTransNo, errCode, errMsg);
|
|
return order;
|
|
}
|
|
}
|
|
|
|
// 免密支付
|
|
Thread.sleep(2000); // 2s
|
|
wxOrder = queryOrder(outTradeNo);
|
|
// 长时间未支付
|
|
if (USER_PAYING.equals(wxOrder.getTradeState()) || PAY_ERROR.equals(wxOrder.getTradeState())) {
|
|
// 撤销订单
|
|
Order cancelOrder = cancelOrder(wxOrder.getOutTradeNo(), wxOrder.getBankTransNo());
|
|
// 撤销成功
|
|
if (cancelOrder.isSuccess()) {
|
|
wxOrder.setTradeState(REVOKED);
|
|
wxOrder.setErrorMsg("订单已撤销");
|
|
}
|
|
}
|
|
return wxOrder;
|
|
} catch (Exception e) {
|
|
log.info("【微信】[盒子支付]异常 {}", e.getMessage());
|
|
order.setErrorMsg("网络异常或当前不支持微信支付");
|
|
ErrorHelper.println(e);
|
|
}
|
|
return order;
|
|
}
|
|
|
|
/**
|
|
* 撤销订单
|
|
*
|
|
* @param outTradeNo 商户订单号
|
|
* @param bankTransNo 银行流水号
|
|
* @return 撤销
|
|
*/
|
|
public static Order cancelOrder(String outTradeNo, String bankTransNo) {
|
|
log.info("【微信】撤销订单 outTradeNo={}, bankTransNo={}", outTradeNo, bankTransNo);
|
|
Order order = new Order();
|
|
try {
|
|
MchReverse mchReverse = new MchReverse();
|
|
String appId = WeChatConfig.APP_ID;
|
|
String mchId = WeChatConfig.MCH_ID;
|
|
String mchKey = WeChatConfig.MCH_KEY;
|
|
|
|
mchReverse.setAppid(appId);
|
|
mchReverse.setMch_id(mchId);
|
|
mchReverse.setOut_trade_no(outTradeNo);
|
|
if (!ObjectUtils.isEmpty(bankTransNo)) {
|
|
mchReverse.setTransaction_id(bankTransNo);
|
|
}
|
|
mchReverse.setNonce_str(CodeHelper.get32UUID());
|
|
mchReverse.setSign_type("MD5");
|
|
|
|
MchReverseResult wxResult = PayMchAPI.secapiPayReverse(mchReverse, mchKey);
|
|
if (wxResult == null) {
|
|
order.setErrorMsg("【微信】撤销订单失败");
|
|
return order;
|
|
}
|
|
|
|
// 调用错误
|
|
if (FAIL.equals(wxResult.getReturn_code())) {
|
|
order.setErrorCode(wxResult.getReturn_code());
|
|
order.setErrorMsg(wxResult.getReturn_msg());
|
|
return order;
|
|
}
|
|
|
|
// 业务错误
|
|
if (FAIL.equals(wxResult.getResult_code())) {
|
|
order.setErrorCode(wxResult.getErr_code());
|
|
order.setErrorMsg(wxResult.getErr_code_des());
|
|
return order;
|
|
}
|
|
|
|
// 交易成功
|
|
if (SUCCESS.equals(wxResult.getResult_code())) {
|
|
order.setSuccess(true); // 订单支付成功(判断条件)
|
|
}
|
|
} catch (Exception e) {
|
|
ErrorHelper.println(e);
|
|
order.setErrorMsg("异常信息:" + e.getMessage());
|
|
}
|
|
return order;
|
|
}
|
|
|
|
|
|
/**
|
|
* 查询退费订单集(含退费时间)
|
|
*
|
|
* @param outTradeNo 订单号
|
|
* @return 订单信息
|
|
*/
|
|
public static List<Bill> queryRefundInfoList(String outTradeNo) throws ServiceException {
|
|
Refundquery refund = new Refundquery();
|
|
|
|
refund.setAppid(WeChatConfig.APP_ID);
|
|
refund.setMch_id(WeChatConfig.MCH_ID);
|
|
refund.setOut_trade_no(outTradeNo);
|
|
refund.setNonce_str(CodeHelper.get32UUID());
|
|
|
|
WxRefundQueryRoot wxResult = WxFactory.Base.Refund().refundQuery(refund, WeChatConfig.MCH_KEY);
|
|
if (wxResult == null) {
|
|
throw new ServiceException(ResultEnum.INTERFACE_WX_INVOKE_ERROR);
|
|
}
|
|
|
|
if (!SUCCESS.equals(wxResult.getReturn_code())) {
|
|
log.info("[微信]查询退款失败{}", wxResult.getReturn_msg());
|
|
throw new ServiceException(ResultEnum.INTERFACE_WX_INVOKE_ERROR);
|
|
}
|
|
|
|
List<Bill> billList = new ArrayList<>();
|
|
if (FAIL.equals(wxResult.getResult_code()) && "REFUNDNOTEXIST".equals(wxResult.getErr_code())) {
|
|
return billList;
|
|
}
|
|
|
|
if (!SUCCESS.equals(wxResult.getResult_code())) {
|
|
throw new ServiceException(ResultEnum.INTERFACE_WX_INVOKE_ERROR);
|
|
}
|
|
|
|
|
|
List<WxRefundItem> refundOrderList = wxResult.getItems();
|
|
if (refundOrderList == null || refundOrderList.size() == 0) {
|
|
return billList;
|
|
}
|
|
|
|
BigDecimal totalFee = new BigDecimal(wxResult.getTotal_fee()).movePointLeft(2);
|
|
|
|
Bill bill;
|
|
String refundStatus;
|
|
for (WxRefundItem item : refundOrderList) {
|
|
refundStatus = item.getRefund_status();
|
|
if (SUCCESS.equals(refundStatus)) {
|
|
bill = new Bill();
|
|
bill.setTotalFee(totalFee);
|
|
bill.setMoney(new BigDecimal(item.getRefund_fee()).movePointLeft(2));
|
|
bill.setRefundId(item.getRefund_id());
|
|
bill.setOutRefundNo(item.getOut_refund_no());
|
|
bill.setRefundChannel(item.getRefund_channel());
|
|
bill.setRefundRecvAccout(item.getRefund_recv_accout());
|
|
bill.setRefundTime(item.getRefund_success_time());
|
|
|
|
billList.add(bill);
|
|
}
|
|
}
|
|
return billList;
|
|
}
|
|
|
|
|
|
/**
|
|
* 查询订单
|
|
*
|
|
* @param outTradeNo 订单号
|
|
* @return 订单信息
|
|
*/
|
|
public static List<Bill> queryRefundList(String outTradeNo) throws ServiceException {
|
|
Refundquery refund = new Refundquery();
|
|
|
|
refund.setAppid(WeChatConfig.APP_ID);
|
|
refund.setMch_id(WeChatConfig.MCH_ID);
|
|
refund.setOut_trade_no(outTradeNo);
|
|
refund.setNonce_str(CodeHelper.get32UUID());
|
|
|
|
RefundqueryResult wxResult = payRefundquery(refund, WeChatConfig.MCH_KEY);
|
|
if (wxResult == null) {
|
|
throw new ServiceException(ResultEnum.INTERFACE_WX_INVOKE_ERROR);
|
|
}
|
|
|
|
if (!SUCCESS.equals(wxResult.getReturn_code())) {
|
|
log.info("[微信]查询退款失败{}", wxResult.getReturn_msg());
|
|
throw new ServiceException(ResultEnum.INTERFACE_WX_INVOKE_ERROR);
|
|
}
|
|
|
|
List<Bill> billList = new ArrayList<>();
|
|
if (FAIL.equals(wxResult.getResult_code()) && "REFUNDNOTEXIST".equals(wxResult.getErr_code())) {
|
|
return billList;
|
|
}
|
|
|
|
if (!SUCCESS.equals(wxResult.getResult_code())) {
|
|
throw new ServiceException(ResultEnum.INTERFACE_WX_INVOKE_ERROR);
|
|
}
|
|
|
|
List<RefundqueryResultItem> refundOrderList = wxResult.getRefundqueryResultItems();
|
|
if (refundOrderList == null || refundOrderList.size() == 0) {
|
|
return billList;
|
|
}
|
|
BigDecimal totalFee = new BigDecimal(wxResult.getTotal_fee()).movePointLeft(2);
|
|
|
|
Bill bill;
|
|
String refundStatus;
|
|
for (RefundqueryResultItem item : refundOrderList) {
|
|
refundStatus = item.getRefund_status();
|
|
if (SUCCESS.equals(refundStatus)) {
|
|
bill = new Bill();
|
|
bill.setTotalFee(totalFee);
|
|
bill.setMoney(new BigDecimal(item.getRefund_fee()).movePointLeft(2));
|
|
bill.setRefundId(item.getRefund_id());
|
|
bill.setOutRefundNo(item.getOut_refund_no());
|
|
bill.setRefundChannel(item.getRefund_channel());
|
|
bill.setRefundRecvAccout(item.getRefund_recv_accout());
|
|
|
|
billList.add(bill);
|
|
}
|
|
}
|
|
return billList;
|
|
}
|
|
|
|
|
|
/**
|
|
* 查询退费订单
|
|
*
|
|
* @param outTradeNo 订单号
|
|
* @return 订单信息
|
|
*/
|
|
public static Bill queryRefund(String outTradeNo, String outRefundNo) throws ServiceException {
|
|
if (ObjectUtils.isEmpty(outTradeNo) || ObjectUtils.isEmpty(outRefundNo)) {
|
|
throw new ServiceException(ResultEnum.PARAM_IS_DEFECT);
|
|
}
|
|
List<Bill> billList = queryRefundList(outTradeNo);
|
|
if (billList.size() == 0) {
|
|
return null;
|
|
}
|
|
for (Bill bill : billList) {
|
|
if (outRefundNo.equals(bill.getOutRefundNo())) {
|
|
return bill;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 查询订单
|
|
*
|
|
* @param outTradeNo 订单号
|
|
* @return 订单信息
|
|
*/
|
|
public static Order queryOrder(String outTradeNo) {
|
|
Order order = new Order();
|
|
order.setOutTradeNo(outTradeNo);
|
|
try {
|
|
MchOrderquery mchOrderquery = new MchOrderquery();
|
|
String appId = WeChatConfig.APP_ID;
|
|
String mchId = WeChatConfig.MCH_ID;
|
|
String mchKey = WeChatConfig.MCH_KEY;
|
|
|
|
mchOrderquery.setAppid(appId);
|
|
mchOrderquery.setMch_id(mchId);
|
|
mchOrderquery.setOut_trade_no(outTradeNo);
|
|
mchOrderquery.setNonce_str(CodeHelper.get32UUID());
|
|
|
|
MchOrderInfoResult wxResult = PayMchAPI.payOrderquery(mchOrderquery, mchKey);
|
|
if (wxResult == null) {
|
|
order.setErrorMsg("【微信】查询订单失败");
|
|
return order;
|
|
}
|
|
|
|
// 调用错误
|
|
if (FAIL.equals(wxResult.getReturn_code())) {
|
|
order.setErrorCode(wxResult.getReturn_code());
|
|
order.setErrorMsg(wxResult.getReturn_msg());
|
|
return order;
|
|
}
|
|
|
|
// 业务错误
|
|
if (FAIL.equals(wxResult.getResult_code())) {
|
|
order.setErrorCode(wxResult.getErr_code());
|
|
order.setErrorMsg(wxResult.getErr_code_des());
|
|
return order;
|
|
}
|
|
|
|
String tradeState = wxResult.getTrade_state();
|
|
order.setTradeState(tradeState);
|
|
|
|
if (SUCCESS.equals(tradeState)) {
|
|
order.setSuccess(true); // 订单支付成功(判断条件)
|
|
|
|
} else if (REFUND.equals(tradeState)) {
|
|
order.setErrorMsg(wxResult.getTrade_state_desc());
|
|
order.setRefund(true); // 订单发生过退款
|
|
} else {
|
|
// 交易错误
|
|
order.setErrorCode(tradeState);
|
|
order.setErrorMsg(wxResult.getTrade_state_desc());
|
|
return order;
|
|
}
|
|
|
|
// 交易成功
|
|
order.setOpenid(wxResult.getOpenid());
|
|
order.setBankTransNo(wxResult.getTransaction_id());
|
|
Integer totalFee = wxResult.getTotal_fee();
|
|
if (totalFee != null) {
|
|
order.setTotalFee(new BigDecimal(totalFee).movePointLeft(2));
|
|
}
|
|
} catch (Exception e) {
|
|
ErrorHelper.println(e);
|
|
order.setErrorMsg("异常信息:" + e.getMessage());
|
|
}
|
|
return order;
|
|
}
|
|
|
|
|
|
/**
|
|
* 查询订单
|
|
*
|
|
* @param transId 支付单号
|
|
* @return 订单信息
|
|
*/
|
|
public static Order queryOrderByTransId(String transId) {
|
|
Order order = new Order();
|
|
order.setBankTransNo(transId);
|
|
try {
|
|
MchOrderquery mchOrderquery = new MchOrderquery();
|
|
|
|
mchOrderquery.setAppid(WeChatConfig.APP_ID);
|
|
mchOrderquery.setMch_id(WeChatConfig.MCH_ID);
|
|
mchOrderquery.setTransaction_id(transId);
|
|
mchOrderquery.setNonce_str(CodeHelper.get32UUID());
|
|
|
|
MchOrderInfoResult wxResult = PayMchAPI.payOrderquery(mchOrderquery, WeChatConfig.MCH_KEY);
|
|
if (wxResult == null) {
|
|
order.setErrorMsg("【微信】查询订单失败");
|
|
return order;
|
|
}
|
|
|
|
// 调用错误
|
|
if (FAIL.equals(wxResult.getReturn_code())) {
|
|
order.setErrorCode(wxResult.getReturn_code());
|
|
order.setErrorMsg(wxResult.getReturn_msg());
|
|
return order;
|
|
}
|
|
|
|
// 业务错误
|
|
if (FAIL.equals(wxResult.getResult_code())) {
|
|
order.setErrorCode(wxResult.getErr_code());
|
|
order.setErrorMsg(wxResult.getErr_code_des());
|
|
return order;
|
|
}
|
|
|
|
String tradeState = wxResult.getTrade_state();
|
|
order.setTradeState(tradeState);
|
|
|
|
if (SUCCESS.equals(tradeState)) {
|
|
order.setSuccess(true); // 订单支付成功(判断条件)
|
|
|
|
} else if (REFUND.equals(tradeState)) {
|
|
order.setErrorMsg(wxResult.getTrade_state_desc());
|
|
order.setRefund(true); // 订单发生过退款
|
|
} else {
|
|
// 交易错误
|
|
order.setErrorCode(tradeState);
|
|
order.setErrorMsg(wxResult.getTrade_state_desc());
|
|
return order;
|
|
}
|
|
|
|
// 交易成功
|
|
order.setOpenid(wxResult.getOpenid());
|
|
order.setBankTransNo(wxResult.getTransaction_id());
|
|
Integer totalFee = wxResult.getTotal_fee();
|
|
if (totalFee != null) {
|
|
order.setTotalFee(new BigDecimal(totalFee).movePointLeft(2));
|
|
}
|
|
} catch (Exception e) {
|
|
ErrorHelper.println(e);
|
|
order.setErrorMsg("异常信息:" + e.getMessage());
|
|
}
|
|
return order;
|
|
}
|
|
|
|
|
|
//
|
|
// /**
|
|
// * 通知成功
|
|
// *
|
|
// * @param response 响应流
|
|
// */
|
|
// public static void notifySuccess(HttpServletResponse response) {
|
|
// notifyEnd(response, "SUCCESS", "");
|
|
// }
|
|
//
|
|
// public static void notifyEnd(HttpServletResponse response, String returnCode, String returnMsg) {
|
|
// try (PrintWriter writer = response.getWriter()) {
|
|
// String xml = "<xml><return_code><![CDATA[" + returnCode + "]]></return_code><return_msg><![CDATA[" + returnMsg + "]]></return_msg></xml>"
|
|
// writer.write(xml);
|
|
// writer.flush();
|
|
// } catch (Exception e) {
|
|
// e.printStackTrace();
|
|
// ErrorHelper.println(e);
|
|
// }
|
|
// }
|
|
|
|
|
|
/**
|
|
* 查询商户账单
|
|
*
|
|
* @return 订单信息
|
|
*/
|
|
public static List<Bill> queryBill(String billType, String date, boolean isCompose) throws ServiceException {
|
|
List<Bill> billList = new ArrayList<>();
|
|
if (!DateHelper.isValidDate(date, DateHelper.DateEnum.yyyy_MM_dd)) {
|
|
throw new ServiceException(ResultEnum.PARAM_DATE_ERROR);
|
|
}
|
|
|
|
Date dateTime = DateHelper.strToDate(date, DateHelper.DateEnum.yyyy_MM_dd);
|
|
if (dateTime == null) {
|
|
throw new ServiceException(ResultEnum.PARAM_DATE_ERROR);
|
|
}
|
|
date = DateHelper.dateToStr(dateTime, DateHelper.DateEnum.yyyyMMdd);
|
|
if (date == null) {
|
|
throw new ServiceException(ResultEnum.PARAM_DATE_ERROR);
|
|
}
|
|
|
|
if (!ALL.equals(billType) && !REFUND.equals(billType) && !SUCCESS.equals(billType)) {
|
|
throw new ServiceException(ResultEnum.PARAM_IS_INVALID);
|
|
}
|
|
|
|
MchDownloadbill mchDownloadbill = new MchDownloadbill();
|
|
|
|
mchDownloadbill.setAppid(WeChatConfig.APP_ID);
|
|
mchDownloadbill.setMch_id(WeChatConfig.MCH_ID);
|
|
mchDownloadbill.setNonce_str(CodeHelper.get32UUID());
|
|
mchDownloadbill.setBill_date(date);
|
|
mchDownloadbill.setBill_type(billType);
|
|
DownloadbillResult downloadbillResult = PayMchAPI.payDownloadbill(mchDownloadbill, WeChatConfig.MCH_KEY);
|
|
|
|
if (downloadbillResult == null) {
|
|
throw new ServiceException(ResultEnum.INTERFACE_WX_INVOKE_ERROR);
|
|
}
|
|
String code = downloadbillResult.getReturn_code();
|
|
String msg = downloadbillResult.getReturn_msg();
|
|
if (FAIL.equals(code)) {
|
|
if ("invalid bill_date".equals(msg)) {
|
|
throw new ServiceException("日期无效,或超过账单的可查询日期范围[invalid bill_date]");
|
|
}
|
|
log.info("[微信]下载对账单错误[{}][{}]", code, msg);
|
|
throw new ServiceException(ResultEnum.INTERFACE_WX_INVOKE_ERROR.message + "[" + msg + "]");
|
|
}
|
|
String data = downloadbillResult.getData();
|
|
if (data == null) {
|
|
throw new ServiceException(ResultEnum.INTERFACE_WX_INVOKE_ERROR);
|
|
}
|
|
String[] dataArr = data.split("\\n");
|
|
if (dataArr.length == 0) {
|
|
return billList;
|
|
}
|
|
|
|
int index;
|
|
Bill billItem;
|
|
String money;
|
|
String outRefundNo;
|
|
String[] titleArr = dataArr[0].split(",");
|
|
if (titleArr.length == 0) {
|
|
return billList;
|
|
}
|
|
|
|
String[] item;
|
|
String tradeState;
|
|
for (int i = 1; i < (dataArr.length - 2); i++) {
|
|
item = dataArr[i].split(","); //27
|
|
billItem = new Bill();
|
|
billItem.setTradeTime(dataHandle(item[0]));
|
|
billItem.setOutTradeNo(dataHandle(item[6]));
|
|
billItem.setBankTransNo(dataHandle(item[5]));
|
|
// billItem.setOpenid(dataHandle(item[7]));
|
|
// billItem.setPayType(dataHandle(item[8]));
|
|
tradeState = dataHandle(item[9]);
|
|
billItem.setTradeState(tradeState);
|
|
if (WxPayHelper.REFUND.equals(tradeState)) { // 退款
|
|
index = findIndex(titleArr, "退款金额");
|
|
if (index != -1) {
|
|
money = dataHandle(item[index]);
|
|
if (money != null) {
|
|
billItem.setMoney(new BigDecimal(money).negate());
|
|
}
|
|
}
|
|
|
|
index = findIndex(titleArr, "商户退款单号");
|
|
if (index != -1) {
|
|
outRefundNo = dataHandle(item[index]);
|
|
if (outRefundNo != null) {
|
|
billItem.setOutRefundNo(outRefundNo);
|
|
}
|
|
}
|
|
|
|
// index = findIndex(titleArr, "退款类型");
|
|
// if (index != -1) {
|
|
// order.setRefundType(dataHandle(item[index]));
|
|
// }
|
|
//
|
|
// index = findIndex(titleArr, "退款状态");
|
|
// if (index != -1) {
|
|
// order.setRefundResult(dataHandle(item[index]));
|
|
// }
|
|
|
|
} else if (WxPayHelper.SUCCESS.equals(tradeState)) { // 成功
|
|
index = findIndex(titleArr, "应结订单金额");
|
|
if (index != -1) {
|
|
money = dataHandle(item[index]);
|
|
if (money != null) {
|
|
billItem.setMoney(new BigDecimal(money));
|
|
}
|
|
}
|
|
}
|
|
billList.add(billItem);
|
|
}
|
|
|
|
if (ALL.equals(billType) && isCompose) {
|
|
List<Bill> refundList = billList.stream().filter(o -> REFUND.equals(o.getTradeState())).collect(Collectors.toList());
|
|
List<Bill> successList = billList.stream().filter(o -> SUCCESS.equals(o.getTradeState())).collect(Collectors.toList());
|
|
|
|
String outTradeNo;
|
|
for (Bill refundItem : refundList) {
|
|
outTradeNo = refundItem.getOutTradeNo();
|
|
for (Bill successItem : successList) {
|
|
if (outTradeNo.equals(successItem.getOutTradeNo())) {
|
|
if (successItem.getHisBills() == null) {
|
|
successItem.setRefundBills(new ArrayList<>());
|
|
}
|
|
refundItem.setBankTransNo(null);
|
|
refundItem.setOutTradeNo(null);
|
|
successItem.getRefundBills().add(refundItem);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return successList;
|
|
}
|
|
return billList;
|
|
}
|
|
|
|
|
|
//
|
|
// /**
|
|
// * 查询商户账单
|
|
// *
|
|
// * @return 订单信息
|
|
// */
|
|
// public static List<Bill> queryBill(String billType, String date) throws ServiceException {
|
|
// List<Bill> billList = new ArrayList<>();
|
|
// if (!DateHelper.isValidDate(date, DateHelper.DateEnum.yyyy_MM_dd)) {
|
|
// throw new ServiceException(ResultEnum.PARAM_DATE_ERROR);
|
|
// }
|
|
//
|
|
// Date dateTime = DateHelper.strToDate(date, DateHelper.DateEnum.yyyy_MM_dd);
|
|
// if (dateTime == null) {
|
|
// throw new ServiceException(ResultEnum.PARAM_DATE_ERROR);
|
|
// }
|
|
// date = DateHelper.dateToStr(dateTime, DateHelper.DateEnum.yyyyMMdd);
|
|
// if (date == null) {
|
|
// throw new ServiceException(ResultEnum.PARAM_DATE_ERROR);
|
|
// }
|
|
//
|
|
// if (!ALL.equals(billType) && !REFUND.equals(billType) && !SUCCESS.equals(billType)) {
|
|
// throw new ServiceException(ResultEnum.PARAM_IS_INVALID);
|
|
// }
|
|
//
|
|
// MchDownloadbill mchDownloadbill = new MchDownloadbill();
|
|
// String appId = WeChatConfig.getAppId();
|
|
// String mchId = WeChatConfig.getMchId();
|
|
// String mchKey = WeChatConfig.getMchKey();
|
|
//
|
|
// mchDownloadbill.setAppid(appId);
|
|
// mchDownloadbill.setMch_id(mchId);
|
|
// mchDownloadbill.setNonce_str(CodeHelper.get32UUID());
|
|
// mchDownloadbill.setBill_date(date);
|
|
// mchDownloadbill.setBill_type(billType);
|
|
// DownloadbillResult downloadbillResult = PayMchAPI.payDownloadbill(mchDownloadbill, mchKey);
|
|
//
|
|
// if (downloadbillResult == null) {
|
|
// throw new ServiceException(ResultEnum.INTERFACE_WX_INVOKE_ERROR);
|
|
// }
|
|
//
|
|
// String data = downloadbillResult.getData();
|
|
// if (data == null) {
|
|
// throw new ServiceException(ResultEnum.INTERFACE_WX_INVOKE_ERROR);
|
|
// }
|
|
// String[] dataArr = data.split("\\n");
|
|
// if (dataArr.length == 0) {
|
|
// return billList;
|
|
// }
|
|
//
|
|
// int index;
|
|
// Bill billItem;
|
|
// String money;
|
|
// String[] titleArr = dataArr[0].split(",");
|
|
// if (titleArr.length == 0) {
|
|
// return billList;
|
|
// }
|
|
//
|
|
// System.out.println(JSONArray.toJSONString(titleArr));
|
|
// for (int i = 1; i < (dataArr.length - 2); i++) {
|
|
// String[] item = dataArr[i].split(","); //27
|
|
// System.out.println(JSONArray.toJSONString(item));
|
|
// billItem = new Bill();
|
|
// billItem.setTradeTime(dataHandle(item[0]));
|
|
// billItem.setOutTradeNo(dataHandle(item[6]));
|
|
// billItem.setBankTransNo(dataHandle(item[5]));
|
|
//// billItem.setOpenid(dataHandle(item[7]));
|
|
//// billItem.setPayType(dataHandle(item[8]));
|
|
// String tradeState = dataHandle(item[9]);
|
|
// billItem.setTradeState(tradeState);
|
|
// if (WxPayHelper.REFUND.equals(tradeState)) { // 退款
|
|
// index = findIndex(titleArr, "退款金额");
|
|
// if (index != -1) {
|
|
// money = dataHandle(item[index]);
|
|
// if (money != null) {
|
|
// billItem.setMoney(new BigDecimal(money).negate());
|
|
// }
|
|
// }
|
|
//
|
|
//// index = findIndex(titleArr, "退款类型");
|
|
//// if (index != -1) {
|
|
//// order.setRefundType(dataHandle(item[index]));
|
|
//// }
|
|
////
|
|
//// index = findIndex(titleArr, "退款状态");
|
|
//// if (index != -1) {
|
|
//// order.setRefundResult(dataHandle(item[index]));
|
|
//// }
|
|
//
|
|
// } else if (WxPayHelper.SUCCESS.equals(tradeState)) { // 成功
|
|
// index = findIndex(titleArr, "应结订单金额");
|
|
// if (index != -1) {
|
|
// money = dataHandle(item[index]);
|
|
// if (money != null) {
|
|
// billItem.setMoney(new BigDecimal(money));
|
|
// }
|
|
// }
|
|
// }
|
|
// billList.add(billItem);
|
|
// }
|
|
// return billList;
|
|
// }
|
|
|
|
// /**
|
|
// * 微信支付调用及通知
|
|
// *
|
|
// * @param request 请求
|
|
// * @param response 响应
|
|
// * @return 微信支付信息
|
|
// */
|
|
// public static PayResult oldPayNotify(HttpServletRequest request, HttpServletResponse response) {
|
|
// PayResult orderInfo = null;
|
|
// InputStream in = null;
|
|
// OutputStream out = null;
|
|
// try {
|
|
// in = request.getInputStream();
|
|
// out = response.getOutputStream();
|
|
//
|
|
// // 获取请求数据
|
|
// String wxXmlData = StreamUtils.copyToString(in, StandardCharsets.UTF_8);
|
|
//
|
|
// // 转换数据对象
|
|
// MchPayNotify wxPayNotify = XMLConverUtil.convertToObject(MchPayNotify.class, wxXmlData);
|
|
// String openid = wxPayNotify.getOpenid();
|
|
// String outTradeNo = wxPayNotify.getOut_trade_no();
|
|
// String bankTransNo = wxPayNotify.getTransaction_id();
|
|
// Integer totalFee = wxPayNotify.getTotal_fee(); // 金额
|
|
// String timeEnd = wxPayNotify.getTime_end();
|
|
// String attach = wxPayNotify.getAttach();
|
|
//
|
|
// if (openid == null || outTradeNo == null || timeEnd == null || bankTransNo == null) {
|
|
// log.info("【微信】下单信息返回错误 outTradeNo={}", outTradeNo);
|
|
// payNotifyError(out);
|
|
// return null;
|
|
// }
|
|
//
|
|
// // 已处理 去重
|
|
// if (KEYS.isContainsKey(bankTransNo)) {
|
|
// log.info("【微信】[重复请求]下单信息去重 outTradeNo={}", outTradeNo);
|
|
// payNotifySuccess(out);
|
|
// return null;
|
|
// }
|
|
//
|
|
// // 将XML转为MAP,确保所有字段都参与签名验证
|
|
// Map<String, String> wxMapData = XMLConverUtil.convertToMap(wxXmlData);
|
|
// StringBuilder wxPayInfo = new StringBuilder();
|
|
// for (String key : wxMapData.keySet()) {
|
|
// wxPayInfo.append(key).append("=").append(wxMapData.get(key)).append(";"); // 拼接微信返回的信息
|
|
// }
|
|
//
|
|
// // @since 2.8.5
|
|
// wxPayNotify.buildDynamicField(wxMapData);
|
|
// // 签名验证
|
|
// if (!SignatureUtil.validateSign(wxMapData, WeChatConfig.MCH_KEY)) { // 验证未通过,通知支付失败
|
|
// log.info("【微信】签名验证未通过,通知支付失败!");
|
|
// payNotifyError(out);
|
|
// return null;
|
|
// }
|
|
//
|
|
// // 验证通过
|
|
// payNotifySuccess(out);
|
|
//
|
|
// // 保存支付结果
|
|
// orderInfo = new PayResult();
|
|
// orderInfo.setOpenid(openid);
|
|
// orderInfo.setOutTradeNo(outTradeNo);
|
|
// orderInfo.setTimeEnd(timeEnd);
|
|
// orderInfo.setTotalFee(new BigDecimal(totalFee).movePointLeft(2));
|
|
// orderInfo.setTransId(bankTransNo);
|
|
// orderInfo.setInfo(wxPayInfo.toString());
|
|
// orderInfo.setAttach(attach);
|
|
//
|
|
// } catch (Exception e) {
|
|
// log.info("【微信】支付通知异常:" + e.getMessage());
|
|
// payNotifySuccess(out);
|
|
// ErrorHelper.println(e);
|
|
// } finally {
|
|
// try {
|
|
// if (in != null) in.close();
|
|
//
|
|
// if (out != null) {
|
|
// if (orderInfo == null) {
|
|
// payNotifySuccess(out);
|
|
// }
|
|
// out.flush();
|
|
// out.close();
|
|
// }
|
|
// } catch (Exception e) {
|
|
// ErrorHelper.println(e);
|
|
// }
|
|
// }
|
|
// return orderInfo;
|
|
// }
|
|
|
|
/**
|
|
* 商户创建订单
|
|
*
|
|
* @param merchantEnum 枚举
|
|
* @param title 商品标题
|
|
* @param totalFee 订单金额
|
|
* @param outTradeNo 订单号
|
|
* @param notifyType 回调类型
|
|
* @param ip ip地址
|
|
* @return 成功返回 json, 否则返回null
|
|
*/
|
|
public static String createNativeOrder(MerchantEnum merchantEnum, String title, BigDecimal totalFee, String outTradeNo, String notifyType, String ip) {
|
|
try {
|
|
if (ObjectUtils.isEmpty(outTradeNo) || merchantEnum == null || totalFee == null || notifyType == null) {
|
|
log.info("【微信】下单参数缺失");
|
|
return null;
|
|
}
|
|
|
|
// 金额转换
|
|
String cents;
|
|
try {
|
|
cents = totalFee.movePointRight(2).toString(); // 单位分
|
|
} catch (Exception e) {
|
|
ErrorHelper.println(e);
|
|
log.info("【微信】统一下单金额转换异常");
|
|
return null;
|
|
}
|
|
|
|
String appId = WeChatConfig.APP_ID;
|
|
String mchId = WeChatConfig.MCH_ID;
|
|
String mchKey = WeChatConfig.MCH_KEY;
|
|
String nonce = UUID.randomUUID().toString().replace("-", "");
|
|
|
|
Unifiedorder unifiedorder = new Unifiedorder();
|
|
unifiedorder.setAppid(appId);
|
|
unifiedorder.setMch_id(mchId);
|
|
unifiedorder.setNonce_str(nonce);
|
|
unifiedorder.setOut_trade_no(outTradeNo);
|
|
unifiedorder.setBody(title);
|
|
|
|
unifiedorder.setTotal_fee(cents); // 金额分
|
|
unifiedorder.setSpbill_create_ip(ip);
|
|
unifiedorder.setNotify_url(WeChatConfig.getBaseUrl() + merchantEnum.QR_NOTIFY_URL);
|
|
unifiedorder.setTrade_type("NATIVE");
|
|
// 额外参数
|
|
unifiedorder.setAttach(notifyType);
|
|
|
|
log.info(appId + ","
|
|
+ mchId + ","
|
|
+ nonce + ","
|
|
+ title + ","
|
|
+ outTradeNo + ","
|
|
+ totalFee + ","
|
|
+ ip + ","
|
|
+ merchantEnum.NOTIFY_URL);
|
|
|
|
// 微信统一下单
|
|
UnifiedorderResult unifiedorderResult = PayMchAPI.payUnifiedorder(unifiedorder, mchKey);
|
|
log.info("【微信】统一下单返回:{}", JsonHelper.toJsonString(unifiedorderResult));
|
|
if (unifiedorderResult == null) {
|
|
log.info("【微信】统一下单失败");
|
|
return null;
|
|
}
|
|
|
|
String result_code = unifiedorderResult.getResult_code();
|
|
// 下单是否成功
|
|
Boolean sign_status = unifiedorderResult.getSign_status();
|
|
if (!SUCCESS.equals(result_code) || sign_status == null || !sign_status) {
|
|
log.info("【微信】统一下单返回异常信息:sign_status={}, err_code=[ {} ], err_code_des=[ {} ]", sign_status, unifiedorderResult.getErr_code(), unifiedorderResult.getErr_code_des());
|
|
return null;
|
|
}
|
|
String codeUrl = unifiedorderResult.getCode_url();
|
|
log.info("codeUrl={}", codeUrl);
|
|
if (codeUrl != null) {
|
|
return codeUrl;
|
|
}
|
|
} catch (Exception e) {
|
|
log.error("【微信】统一下单异常信息:" + e.getMessage());
|
|
ErrorHelper.println(e);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
public static String dataHandle(String data) {
|
|
if (ObjectUtils.isEmpty(data)) {
|
|
return null;
|
|
}
|
|
return data.substring(1);
|
|
}
|
|
|
|
public static int findIndex(String[] titleArr, String title) {
|
|
if (titleArr == null || titleArr.length == 0) {
|
|
return -1;
|
|
}
|
|
|
|
for (int i = 0; i < titleArr.length; i++) {
|
|
if (title.equals(titleArr[i])) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
}
|
|
|