|
@@ -1,7 +1,10 @@
|
|
|
package com.cyksj.service.wechat.impl;
|
|
package com.cyksj.service.wechat.impl;
|
|
|
|
|
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
|
|
+import cn.hutool.core.util.CharsetUtil;
|
|
|
|
|
+import cn.hutool.http.ssl.SSLSocketFactoryBuilder;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
import com.cyksj.common.exception.BusinessRuntimeException;
|
|
import com.cyksj.common.exception.BusinessRuntimeException;
|
|
|
import com.cyksj.common.util.*;
|
|
import com.cyksj.common.util.*;
|
|
|
import com.cyksj.config.BaseWeChatConfig;
|
|
import com.cyksj.config.BaseWeChatConfig;
|
|
@@ -9,7 +12,9 @@ import com.cyksj.config.WeChatConfig;
|
|
|
import com.cyksj.config.WeChatFactory;
|
|
import com.cyksj.config.WeChatFactory;
|
|
|
import com.cyksj.enums.WeChatAuthRedirectUrl;
|
|
import com.cyksj.enums.WeChatAuthRedirectUrl;
|
|
|
import com.cyksj.mapper.WxAppMapper;
|
|
import com.cyksj.mapper.WxAppMapper;
|
|
|
|
|
+import com.cyksj.mapper.channel.ShopConfigMapper;
|
|
|
import com.cyksj.model.dto.*;
|
|
import com.cyksj.model.dto.*;
|
|
|
|
|
+import com.cyksj.model.entity.ShopConfig;
|
|
|
import com.cyksj.model.entity.WxApp;
|
|
import com.cyksj.model.entity.WxApp;
|
|
|
import com.cyksj.service.wechat.WeChatService;
|
|
import com.cyksj.service.wechat.WeChatService;
|
|
|
import com.cyksj.service.wechat.WxMpAccountOps;
|
|
import com.cyksj.service.wechat.WxMpAccountOps;
|
|
@@ -21,10 +26,15 @@ import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
import javax.crypto.Mac;
|
|
import javax.crypto.Mac;
|
|
|
import javax.crypto.spec.SecretKeySpec;
|
|
import javax.crypto.spec.SecretKeySpec;
|
|
|
|
|
+import javax.net.ssl.KeyManagerFactory;
|
|
|
|
|
+import java.io.File;
|
|
|
|
|
+import java.io.FileInputStream;
|
|
|
|
|
+import java.io.InputStream;
|
|
|
import java.math.BigDecimal;
|
|
import java.math.BigDecimal;
|
|
|
import java.net.URLEncoder;
|
|
import java.net.URLEncoder;
|
|
|
import java.net.http.HttpRequest;
|
|
import java.net.http.HttpRequest;
|
|
|
import java.net.http.HttpResponse;
|
|
import java.net.http.HttpResponse;
|
|
|
|
|
+import java.security.KeyStore;
|
|
|
import java.util.Arrays;
|
|
import java.util.Arrays;
|
|
|
import java.util.Date;
|
|
import java.util.Date;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
@@ -48,6 +58,7 @@ public class WeChatServiceImpl implements WeChatService {
|
|
|
|
|
|
|
|
private final WxAppMapper wxAppMapper;
|
|
private final WxAppMapper wxAppMapper;
|
|
|
|
|
|
|
|
|
|
+ private final ShopConfigMapper shopConfigMapper;
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public String createUrl(String state, String redirectUrl) {
|
|
public String createUrl(String state, String redirectUrl) {
|
|
@@ -184,16 +195,16 @@ public class WeChatServiceImpl implements WeChatService {
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
- public H5JsPayParams getJsPayParams(String appid, String openid, Integer totalFee, String outTradeNo, String notifyUrl, String attach, String body, String tradeType, Date expireTime) throws Exception {
|
|
|
|
|
|
|
+ public H5JsPayParams getJsPayParams(String appid, String shopId, String openid, Integer totalFee, String outTradeNo, String notifyUrl, String attach, String body, String tradeType, Date expireTime) throws Exception {
|
|
|
log.info("------------------- 调用微信h5支付 开始 -------------------");
|
|
log.info("------------------- 调用微信h5支付 开始 -------------------");
|
|
|
- BaseWeChatConfig weChatConfigStrategy = WeChatFactory.getWeChatConfigStrategy(appid);
|
|
|
|
|
|
|
+ ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class).eq(ShopConfig::getAppId, shopId).last(" limit 1"));
|
|
|
|
|
|
|
|
// 拼接统一下单实体类
|
|
// 拼接统一下单实体类
|
|
|
UnifiedOrder order = new UnifiedOrder()
|
|
UnifiedOrder order = new UnifiedOrder()
|
|
|
.setAppid(appid)
|
|
.setAppid(appid)
|
|
|
.setAttach(attach)
|
|
.setAttach(attach)
|
|
|
.setBody(body)
|
|
.setBody(body)
|
|
|
- .setMchId(weChatConfigStrategy.getShopid())
|
|
|
|
|
|
|
+ .setMchId(shopConfig.getAppId())
|
|
|
.setNonceStr("chan.123")
|
|
.setNonceStr("chan.123")
|
|
|
.setNotifyUrl(notifyUrl)
|
|
.setNotifyUrl(notifyUrl)
|
|
|
.setOutTradeNo(outTradeNo)
|
|
.setOutTradeNo(outTradeNo)
|
|
@@ -209,7 +220,7 @@ public class WeChatServiceImpl implements WeChatService {
|
|
|
}
|
|
}
|
|
|
String sign = Codec.DoDigest.custom()
|
|
String sign = Codec.DoDigest.custom()
|
|
|
.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
|
|
.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
|
|
|
- .setStringData(order.getPrintln(tradeType, weChatConfigStrategy.getShopKey()))
|
|
|
|
|
|
|
+ .setStringData(order.getPrintln(tradeType, shopConfig.getSecret()))
|
|
|
.toHexString()
|
|
.toHexString()
|
|
|
.toUpperCase();
|
|
.toUpperCase();
|
|
|
order.setSign(sign);
|
|
order.setSign(sign);
|
|
@@ -244,7 +255,7 @@ public class WeChatServiceImpl implements WeChatService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 校验签名
|
|
// 校验签名
|
|
|
- boolean f = this.checkSignWithMd5(wxResult,weChatConfigStrategy.getShopKey());
|
|
|
|
|
|
|
+ boolean f = this.checkSignWithMd5(wxResult,shopConfig.getSecret());
|
|
|
|
|
|
|
|
if (!f) {
|
|
if (!f) {
|
|
|
throw BusinessRuntimeException.getInstance("调用微信h5支付, 微信返回值的签名验证失败.");
|
|
throw BusinessRuntimeException.getInstance("调用微信h5支付, 微信返回值的签名验证失败.");
|
|
@@ -259,7 +270,7 @@ public class WeChatServiceImpl implements WeChatService {
|
|
|
|
|
|
|
|
sign = Codec.DoDigest.custom()
|
|
sign = Codec.DoDigest.custom()
|
|
|
.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
|
|
.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
|
|
|
- .setStringData(params.println(weChatConfigStrategy.getShopKey()))
|
|
|
|
|
|
|
+ .setStringData(params.println(shopConfig.getSecret()))
|
|
|
.toHexString()
|
|
.toHexString()
|
|
|
.toUpperCase();
|
|
.toUpperCase();
|
|
|
params.setPaySign(sign);
|
|
params.setPaySign(sign);
|
|
@@ -394,13 +405,15 @@ public class WeChatServiceImpl implements WeChatService {
|
|
|
log.info("发送模板消息结束,返回值:{}", send != null ? send.body() : null);
|
|
log.info("发送模板消息结束,返回值:{}", send != null ? send.body() : null);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
@Override
|
|
@Override
|
|
|
- public void refundWxOrder(String appId, String transactionId, String outRefundNo, BigDecimal totalFee, BigDecimal refundMoney, String notifyUrl) throws Exception {
|
|
|
|
|
- BaseWeChatConfig weChatConfigStrategy = WeChatFactory.getWeChatConfigStrategy(appId);
|
|
|
|
|
|
|
+ public void refundWxOrder(String appId,String shopId, String transactionId, String outRefundNo, BigDecimal totalFee, BigDecimal refundMoney, String notifyUrl) throws Exception {
|
|
|
|
|
+ ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class).eq(ShopConfig::getAppId, shopId).last(" limit 1"));
|
|
|
|
|
+
|
|
|
WxRefundOrder wxRefundOrder = new WxRefundOrder();
|
|
WxRefundOrder wxRefundOrder = new WxRefundOrder();
|
|
|
wxRefundOrder.setAppid(appId);
|
|
wxRefundOrder.setAppid(appId);
|
|
|
//商户号
|
|
//商户号
|
|
|
- wxRefundOrder.setMchId(weChatConfigStrategy.getShopid());
|
|
|
|
|
|
|
+ wxRefundOrder.setMchId(shopConfig.getAppId());
|
|
|
wxRefundOrder.setOutRefundNo(outRefundNo);
|
|
wxRefundOrder.setOutRefundNo(outRefundNo);
|
|
|
wxRefundOrder.setNonceStr("chan123");
|
|
wxRefundOrder.setNonceStr("chan123");
|
|
|
wxRefundOrder.setTotalFee(totalFee.intValue());
|
|
wxRefundOrder.setTotalFee(totalFee.intValue());
|
|
@@ -411,23 +424,32 @@ public class WeChatServiceImpl implements WeChatService {
|
|
|
wxRefundOrder.setNotifyUrl(notifyUrl);
|
|
wxRefundOrder.setNotifyUrl(notifyUrl);
|
|
|
String sign = Codec.DoDigest.custom()
|
|
String sign = Codec.DoDigest.custom()
|
|
|
.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
|
|
.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
|
|
|
- .setStringData(wxRefundOrder.println(weChatConfigStrategy.getShopKey()))
|
|
|
|
|
|
|
+ .setStringData(wxRefundOrder.println(shopConfig.getSecret()))
|
|
|
.toHexString()
|
|
.toHexString()
|
|
|
.toUpperCase();
|
|
.toUpperCase();
|
|
|
wxRefundOrder.setSign(sign);
|
|
wxRefundOrder.setSign(sign);
|
|
|
|
|
|
|
|
String xml = Xmls.toXml(wxRefundOrder);
|
|
String xml = Xmls.toXml(wxRefundOrder);
|
|
|
- HttpResponse<byte[]> res = J11HttpC.custom()
|
|
|
|
|
- .ofPost()
|
|
|
|
|
- .url("https://api.mch.weixin.qq.com/secapi/pay/refund")
|
|
|
|
|
- .headers(J11HttpC.ReqType.raw_xml)
|
|
|
|
|
- .cacheURI()
|
|
|
|
|
- .body(HttpRequest.BodyPublishers.ofString(xml, IoKit.Charsets.UTF_8.getCharset()))
|
|
|
|
|
- // 指定携带ssl证书的httpClient 进行请求
|
|
|
|
|
- .send(J11HttpC.Client.WX_REFUND, HttpResponse.BodyHandlers.ofByteArray());
|
|
|
|
|
|
|
|
|
|
- if (200 != res.statusCode()) {
|
|
|
|
|
- throw BusinessRuntimeException.getInstance("请求wx_refund失败: " + IoKit.toString(res.body()));
|
|
|
|
|
|
|
+ KeyStore keyStore = KeyStore.getInstance("PKCS12");
|
|
|
|
|
+ File file = new File("cert/" + shopId + ".p12");
|
|
|
|
|
+ InputStream inputStream = new FileInputStream(file);
|
|
|
|
|
+ keyStore.load(inputStream, shopId.toCharArray());
|
|
|
|
|
+ // 初始化密钥库
|
|
|
|
|
+ KeyManagerFactory factory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
|
|
|
|
+ factory.init(keyStore, shopId.toCharArray());
|
|
|
|
|
+ cn.hutool.http.HttpRequest request = cn.hutool.http.HttpRequest.post("https://api.mch.weixin.qq.com/secapi/pay/refund")
|
|
|
|
|
+ // 自定义返回编码
|
|
|
|
|
+ .charset(CharsetUtil.CHARSET_UTF_8)
|
|
|
|
|
+ // 禁用缓存
|
|
|
|
|
+ .disableCache()
|
|
|
|
|
+ .setSSLSocketFactory(SSLSocketFactoryBuilder.create()
|
|
|
|
|
+ .setKeyManagers(factory.getKeyManagers())
|
|
|
|
|
+ .setProtocol(SSLSocketFactoryBuilder.TLSv1).build());
|
|
|
|
|
+ cn.hutool.http.HttpResponse res = request.body(xml).execute();
|
|
|
|
|
+
|
|
|
|
|
+ if (200 != res.getStatus()) {
|
|
|
|
|
+ throw BusinessRuntimeException.getInstance("请求wx_refund失败: " + res.body());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Map<String, String> wxRefund = Xmls.toMap(res.body());
|
|
Map<String, String> wxRefund = Xmls.toMap(res.body());
|
|
@@ -441,7 +463,7 @@ public class WeChatServiceImpl implements WeChatService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 校验签名
|
|
// 校验签名
|
|
|
- boolean f = this.checkSignWithMd5(wxRefund, weChatConfigStrategy.getShopKey());
|
|
|
|
|
|
|
+ boolean f = this.checkSignWithMd5(wxRefund, shopConfig.getSecret());
|
|
|
if (!f) {
|
|
if (!f) {
|
|
|
throw BusinessRuntimeException.getInstance("调用微信h5申请退款, 微信返回值的签名验证失败.");
|
|
throw BusinessRuntimeException.getInstance("调用微信h5申请退款, 微信返回值的签名验证失败.");
|
|
|
}
|
|
}
|