Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
tech.mhuang.pacebox.springboot.payment.wechat.WechatPayServer Maven / Gradle / Ivy
package tech.mhuang.pacebox.springboot.payment.wechat;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import tech.mhuang.pacebox.core.exception.BusinessException;
import tech.mhuang.pacebox.core.util.StringUtil;
import tech.mhuang.pacebox.springboot.core.okhttp.OkHttpDataType;
import tech.mhuang.pacebox.springboot.core.okhttp.OkhttpClientUtil;
import tech.mhuang.pacebox.springboot.payment.dto.WechatPayDTO;
import tech.mhuang.pacebox.springboot.payment.dto.WechatRefundDTO;
import tech.mhuang.pacebox.springboot.payment.wechat.util.BigDecimalUtil;
import tech.mhuang.pacebox.springboot.payment.wechat.util.PayCommonUtil;
import tech.mhuang.pacebox.springboot.payment.wechat.util.WechatConfigUtil;
import tech.mhuang.pacebox.springboot.payment.wechat.util.XMLUtil;
import tech.mhuang.pacebox.springboot.protocol.Result;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Stream;
/**
* 微信支付服务
*
* @author mhuang
* @since 1.0.0
*/
@Slf4j
public class WechatPayServer {
private final static String APP_MODE = "APP";
/**
* 小程序、微信H5
*/
private final static String JSAPI_MODE = "JSAPI";
private final static List SUPPORT_MODE_LIST = Stream.of(APP_MODE, JSAPI_MODE).toList();
private final static String OK = "OK";
/**
* 微信支付
*
* @param dto 支付的DTO
* @return 返回支付实体
* @throws Exception 异常
*/
public static Map, ?> payment(WechatPayDTO dto) throws Exception {
SortedMap packageParams = createCommonParmas(dto.getAppId(), dto.getMchId());
if (SUPPORT_MODE_LIST.contains(dto.getMode().toUpperCase())) {
if (APP_MODE.equalsIgnoreCase(dto.getMode())) {
return createAppPay(packageParams, dto.getTradeNo(), dto.getSubject(), dto.getAmount(), dto.getApiKey(), dto.getIp(), dto.getNotifyUrl(), dto.getProxyIp(), dto.getProxyPort());
} else if (JSAPI_MODE.equalsIgnoreCase(dto.getMode())) {
return createJsApiPay(packageParams, dto.getTradeNo(), dto.getSubject(), dto.getAmount(), dto.getApiKey(), dto.getIp(), dto.getNotifyUrl(), dto.getProxyIp(), dto.getProxyPort(), dto.getOpenId());
}
}
throw new BusinessException(500, "暂不支持支付" + dto.getMode() + "方式");
}
/**
* 微信退款
*
* @param dto 退款的实体
* @return 退款结果
* @throws Exception 异常
*/
public static Map, ?> refundOrder(WechatRefundDTO dto) throws Exception {
SortedMap packageParams = createCommonParmas(dto.getAppId(), dto.getMchId());
packageParams.put("out_trade_no", dto.getTradeNo());
// 商户订单号
packageParams.put("out_refund_no", dto.getOutRefundNo());
// 商户退款单号
packageParams.put("total_fee", dto.getTotalFee());
// 订单金额
packageParams.put("refund_fee", dto.getRefundFee());
// 退款金额
if (StringUtil.isNotBlank(dto.getFeeType())) {
packageParams.put("refund_fee_type", dto.getFeeType());
// 退款币种
}
if (StringUtil.isNotBlank(dto.getRefundDesc())) {
packageParams.put("refund_desc", dto.getRefundDesc());
// 退款原因
}
if (StringUtil.isNotBlank(dto.getNotifyUrl())) {
packageParams.put("notify_url", dto.getNotifyUrl());
// 退款结果通知url
}
//密匙
String sign = PayCommonUtil.createSign("UTF-8", packageParams, dto.getApiKey());
// 签名
packageParams.put("sign", sign);
String requestXml = PayCommonUtil.getRequestXml(packageParams);
OkHttpClient okHttpClient = OkhttpClientUtil.genOkHttpClient(dto.getProxyHost(), dto.getProxyPort(), dto.getCertPath(), dto.getMchId()).build();
Request request = new Request.Builder().url(WechatConfigUtil.REFUND_URL)
.post(RequestBody.create(requestXml,OkHttpDataType.XML_DATA_TYPE))
.build();
Response response = okHttpClient.newCall(request).execute();
if (response.isSuccessful()) {
assert response.body() != null;
return XMLUtil.doXmlParse(response.body().string());
} else {
throw new BusinessException(Result.SYS_FAILD, response.message());
}
}
public static SortedMap createCommonParmas(String appId, String mchId) {
SortedMap packageParams = new TreeMap<>();
WechatConfigUtil.commonParams(packageParams, appId, mchId);
return packageParams;
}
public static Map, ?> createAppPay(SortedMap packageParams,
String tradeNo, String subject, String totalFee, String apiKey,
String ip, String notifyUrl) throws Exception {
return createAppPay(packageParams, tradeNo, subject, totalFee, apiKey, ip, notifyUrl, null, 0);
}
public static Map, ?> createAppPay(SortedMap packageParams,
String tradeNo, String subject, String totalFee, String apiKey,
String ip, String notifyUrl, String proxyIp, int proxyPort) throws Exception {
return createBasePay(packageParams, tradeNo, subject, totalFee, apiKey, ip, notifyUrl, proxyIp, proxyPort, APP_MODE, null);
}
public static Map, ?> createJsApiPay(SortedMap packageParams,
String tradeNo, String subject, String totalFee, String apiKey,
String ip, String notifyUrl, String openid) throws Exception {
return createJsApiPay(packageParams, tradeNo, subject, totalFee, apiKey, ip, notifyUrl, null, 0, openid);
}
public static Map, ?> createJsApiPay(SortedMap packageParams,
String tradeNo, String subject, String totalFee, String apiKey,
String ip, String notifyUrl, String proxyIp, int proxyPort, String openid) throws Exception {
// 账号信息
return createBasePay(packageParams, tradeNo, subject, totalFee, apiKey, ip, notifyUrl, proxyIp, proxyPort, JSAPI_MODE, openid);
}
public static Map, ?> createBasePay(SortedMap packageParams,
String tradeNo, String subject, String totalFee, String apiKey,
String ip, String notifyUrl, String proxyIp, int proxyPort, String appMode, String openid) throws Exception {
// 商品描述
packageParams.put("body", subject);
// 商户订单号
packageParams.put("out_trade_no", tradeNo);
totalFee = BigDecimalUtil.subZeroAndDot(totalFee);
// 总金额
packageParams.put("total_fee", totalFee);
//H5支付要求商户在统一下单接口中上传用户真实ip地址 spbill_create_ip
// 发起人IP地址
packageParams.put("spbill_create_ip", ip);
// 回调地址
packageParams.put("notify_url", notifyUrl);
// 交易类型
packageParams.put("trade_type", appMode);
packageParams.put("nonce_str", PayCommonUtil.createNoncestr());
if (JSAPI_MODE.equalsIgnoreCase(appMode)) {
packageParams.put("openid", openid);
}
String sign = PayCommonUtil.createSign("UTF-8", packageParams, apiKey);
//密匙
packageParams.put("sign", sign);
log.debug("微信支付打印的数据是:{}", packageParams);
// 签名
String requestXml = PayCommonUtil.getRequestXml(packageParams);
OkHttpClient okHttpClient = OkhttpClientUtil.genOkHttpClient(proxyIp, proxyPort).build();
Request request = new Request.Builder().url(WechatConfigUtil.UNIFIED_ORDER_URL)
.post(RequestBody.create(requestXml,OkHttpDataType.XML_DATA_TYPE))
.build();
try(Response response = okHttpClient.newCall(request).execute()){
if (response.isSuccessful() || StringUtil.equals(response.message(), OK)) {
assert response.body() != null;
return XMLUtil.doXmlParse(response.body().string());
} else {
throw new BusinessException(500, response.message());
}
}
}
}