t = new SubscribeEntity<>();
+ t.setTouser(toUser);
+ t.setTemplate_id(SUBSCRIBE_MSG_ID_ORDERSEND);
+ t.setData(new ReceiveSubscriOrderSendData(params));
+ System.out.println(JacksonUtil.beanToJson(t));
+ ret = HttpsUtil.httpsRequest(url, "POST", JacksonUtil.beanToJson(t));
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ //ok: {"errcode":0,"errmsg":"ok"}
+ //err: {"errcode":43101,"errmsg":"user refuse to accept the msg hint: [V_GEdA02503942]"}
+ System.out.println("Send Subscribe Message:" + ret);
+ String errCode = JacksonUtil.getJsonValue(ret, "errcode");
+ System.out.println(errCode);
+ return errCode.equals("0");
+ }
+}
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/payutil/WxPayDirectUtils.java b/util_wechat/src/main/java/com/ccsens/wechatutil/payutil/WxPayDirectUtils.java
similarity index 97%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/payutil/WxPayDirectUtils.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/payutil/WxPayDirectUtils.java
index c4039a1..ea17d0e 100644
--- a/wechatutil/src/main/java/com/ccsens/wechatutil/payutil/WxPayDirectUtils.java
+++ b/util_wechat/src/main/java/com/ccsens/wechatutil/payutil/WxPayDirectUtils.java
@@ -1,322 +1,322 @@
-package com.ccsens.wechatutil.payutil;
-
-import cn.hutool.core.util.StrUtil;
-import com.alibaba.fastjson.JSONObject;
-import com.ccsens.wechatutil.exception.PayException;
-import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
-import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
-import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
-import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
-import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
-import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.utils.URIBuilder;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.util.EntityUtils;
-
-import javax.servlet.http.HttpServletRequest;
-import java.io.*;
-import java.math.BigInteger;
-import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
-import java.security.PrivateKey;
-import java.security.Signature;
-import java.util.Base64;
-import java.util.UUID;
-
-/**
- * 微信直连商户支付
- * @author :mr.zhangsan
- * @date :Created in 2021/6/18 23:58
- * @version v1.0:
- */
-@Slf4j
-public class WxPayDirectUtils {
-
- //商户支付URL
- private static final String URL_TRANSACTIONS
- = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
- //测试小程序号appid
- public static final String TK_APPID = "wxa26bb3e3f1d2d998";
- //测试商户号
- public static final String TK_MCHID = "1603930405";
- //测试小程序秘钥secret
- public static final String TK_SECRET = "162cc6eb70bc341bc67fea210796be21";
- //商户私钥
- private static PrivateKey privateKey;
- //版本>=0.1.5可使用 AutoUpdateCertificatesVerifier 类替代默认的验签器。
- // 它会在构造时自动下载商户对应的微信支付平台证书,并每隔一段时间(默认为1个小时)更新证书。
- private static AutoUpdateCertificatesVerifier verifier = null;
- //WechatPayHttpClient
- private static HttpClient httpClient = null;
- //测试商户证书存放路径
- private static final String Client_Key_Path = "C:\\home\\fxxt\\cert_tk\\apiclient_key.pem";
- //测试商户v3key
- private static final String DIRECT_V3_Key = "5IDIy173oyjSGPZHuP0lc2V3UqFBO55M";
- //测试证书序列号
- private static final String DIRECT_CERT_SERIAL_NO = "368344414C13EA2ABF3A59A8CF3F31E99ACE0058";
-
-
- /**
- * 支付订单状态
- */
- public enum PayOrderStatus {
- SUCCESS, NOTPAY, CLOSED, REVOKED, USERPAYING, PAYERROR, FAILED, UNKNOWN
- }
-
-
- /**
- * 商户统一下单支付
- *
- * 应用ID appid string[1,32] 是 body 由微信生成的应用ID,全局唯一。请求基础下单接口时请注意APPID的应用属性,例如公众号场景下,需使用应用属性为公众号的APPID
- * 示例值:wxd678efh567hg6787
- * 直连商户号 mchid string[1,32] 是 body 直连商户的商户号,由微信支付生成并下发。
- * 示例值:1230000109
- * 商品描述 description string[1,127] 是 body 商品描述
- * 示例值:Image形象店-深圳腾大-QQ公仔
- * 商户订单号 out_trade_no string[6,32] 是 body 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
- * 示例值:1217752501201407033233368018
- * 交易结束时间 time_expire string[1,64] 否 body 订单失效时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
- * 示例值:2018-06-08T10:34:56+08:00
- * 附加数据 attach string[1,128] 否 body 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用
- * 示例值:自定义数据
- * 通知地址 notify_url string[1,256] 是
- */
- public static JSONObject transactions(String openid, String outTradeNo, String description, String notifyUrl, int totalFee) throws Exception {
- HttpPost httpPost = new HttpPost(URL_TRANSACTIONS);
- httpPost.addHeader("Accept", "application/json");
- httpPost.addHeader("Content-type", "application/json; charset=utf-8");
-
- JSONObject params = new JSONObject();
- JSONObject amount = new JSONObject();
- JSONObject payer = new JSONObject();
- payer.put("openid", openid);
-
- amount.put("total", totalFee);
- amount.put("currency", "CNY");
-
- params.put("appid", TK_APPID);
- params.put("mchid", TK_MCHID);
- params.put("out_trade_no", outTradeNo);
- params.put("description", description);
- params.put("notify_url", notifyUrl);
- params.put("amount", amount);
- params.put("payer", payer);
-
- httpPost.setEntity(new StringEntity(params.toJSONString(), "UTF-8"));
- CloseableHttpResponse response = (CloseableHttpResponse) getWechatPayHttpClient().execute(httpPost);
- String bodyAsString = EntityUtils.toString(response.getEntity());
- JSONObject respJson = JSONObject.parseObject(bodyAsString);
-
- Object prepayId = respJson.get("prepay_id");
- Object code = respJson.get("code");
-
- if (code != null) {
- throw new Exception(respJson.get("message").toString());
- }
- JSONObject result = new JSONObject();
- //根据返回的prepay_id生成发起支付需要的参数签名返回前端
-
- result.put("appId", TK_APPID);
- result.put("timeStamp", System.currentTimeMillis() / 1000);
- result.put("nonceStr", createNonceStr());
- result.put("package", "prepay_id=" + prepayId);
- result.put("signType", "RSA");
-
- String message = TK_APPID + "\n"
- + result.get("timeStamp") + "\n"
- + result.get("nonceStr") + "\n"
- + result.get("package") + "\n";
- String sign = wxPayReqSign(message.getBytes("utf-8"));
- result.put("paySign", sign);
- return result;
- }
-
- /**
- * 解析支付完毕微信通知参数
- *
- * signature 头部签名 Wechatpay-Signature
- * body json消息
- * @return
- * @throws IOException 参数名 变量 类型[长度限制] 必填 描述
- */
- public static JSONObject rechargeResult(HttpServletRequest request) throws Exception {
- log.info("解析支付完毕微信通知参数");
- //一、验证签名
- //1.1获取平台证书
- getVerifier();
- //1.2检查平台证书序列号
- String wepaySerial = request.getHeader("Wechatpay-Serial");
- if (wepaySerial == null) {
- throw new PayException(-9, "平台证书序列号为空");
- }
- log.info("获取平台证书序列号");
- //获取平台证书序列号
- BigInteger currentSerial = getVerifier().getValidCertificate().getSerialNumber();
- if (StrUtil.isEmpty(wepaySerial) || !wepaySerial.equalsIgnoreCase(currentSerial.toString(16))) {
- throw new PayException(-9, "证书序列号不一致");
- }
- log.info("3构造验签名串");
- //1.3构造验签名串
- String wepayNonce = request.getHeader("Wechatpay-Nonce");
- String wepayTimestamp = request.getHeader("Wechatpay-Timestamp");
- String wepayBody = null;
- BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
- String line = null;
- StringBuilder body = new StringBuilder();
- while ((line = br.readLine()) != null) {
- body.append(line);
- }
- if (StrUtil.isEmpty(body.toString())) {
- throw new PayException(-9, "body is null");
- }
- wepayBody = body.toString();
-
-
- String message = wepayTimestamp + "\n"
- + wepayNonce + "\n"
- + body.toString() + "\n";
- log.info("获取应答签名");
- //1.4获取应答签名
- String wepySignature = request.getHeader("Wechatpay-Signature");
-
- //1.5验证签名
- boolean rr = getVerifier().verify(wepaySerial,
- message.getBytes(StandardCharsets.UTF_8),wepySignature);
- if (!rr){
- //TODO 签名验证失败抛异常
- }
-// String sign = wxPayRespSign(message.getBytes("utf-8"));
-// if (!wepySignature.equals(sign)) {
-// throw new PayException(-9, "验证签名不一致");
-// }
- log.info("解密数据");
- //二、解密数据
- JSONObject jsonObject = JSONObject.parseObject(wepayBody);
- JSONObject resource = (JSONObject) jsonObject.get("resource");
- AesUtil aesUtil = new AesUtil(DIRECT_V3_Key.getBytes("utf-8"));
- //解密
- String decryptToString = aesUtil.decryptToString(
- resource.get("associated_data").toString().getBytes(),
- resource.get("nonce").toString().getBytes(),
- resource.get("ciphertext").toString());
- JSONObject parseObject = JSONObject.parseObject(decryptToString);
- return parseObject;
- }
-
- private static PayOrderStatus getPayOrderStatus(URIBuilder uriBuilder) throws URISyntaxException, IOException {
- HttpGet httpGet = new HttpGet(uriBuilder.build());
- httpGet.addHeader("Accept", "application/json");
-
- CloseableHttpResponse response = (CloseableHttpResponse) getWechatPayHttpClient().execute(httpGet);
-
- String bodyAsString = EntityUtils.toString(response.getEntity());
-
- JSONObject jsonObject = JSONObject.parseObject(bodyAsString);
- log.info("json:{}", jsonObject);
- Object trade_state = jsonObject.get("trade_state");
- if (trade_state != null) {
- String tradeState = trade_state.toString();
- log.info("PayOrderStatus:{}",tradeState);
- if ("SUCCESS".equals(tradeState)) {
- return PayOrderStatus.SUCCESS;
- } else if ("USERPAYING".equals(tradeState)) {
- return PayOrderStatus.USERPAYING;
- } else {
- return PayOrderStatus.FAILED;
- }
- }
- return PayOrderStatus.UNKNOWN;
- }
-
- /**
- * 商户订单号查询
- *
- * @param transactionId 微信订单号
- * @return
- * @throws IOException
- * @throws URISyntaxException
- */
- public static PayOrderStatus wechatOrder(String transactionId) throws IOException, URISyntaxException {
- URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + transactionId + "?mchid=" + TK_MCHID);
- return getPayOrderStatus(uriBuilder);
- }
-
- /**
- * 根据商户证书,获取私钥
- *
- * @return
- * @throws FileNotFoundException
- */
- public static PrivateKey getPrivateKey() throws FileNotFoundException {
- if (privateKey == null) {
- privateKey = PemUtil.loadPrivateKey(
- new FileInputStream(Client_Key_Path));
- }
- return privateKey;
- }
-
- /**
- * 依据商户证书私钥进行签名
- *
- * @param message
- * @return
- * @throws Exception
- */
- public static String wxPayReqSign(byte[] message) throws Exception {
- Signature sign = Signature.getInstance("SHA256withRSA");
- sign.initSign(getPrivateKey());
- sign.update(message);
-
- return Base64.getEncoder().encodeToString(sign.sign());
- }
-
- /**
- * 根据微信平台证书获取httpclient
- *
- * @return
- * @throws FileNotFoundException
- * @throws UnsupportedEncodingException
- */
- public static HttpClient getWechatPayHttpClient() throws FileNotFoundException, UnsupportedEncodingException {
- if (httpClient == null) {
- //构造WechatPayHttpClientBuilder
- WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
- .withMerchant(TK_MCHID, DIRECT_CERT_SERIAL_NO, getPrivateKey())
- .withValidator(new WechatPay2Validator(getVerifier()));
-
- // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
- httpClient = builder.build();
- }
- return httpClient;
- }
-
- /**
- * 自动获取微信平台证书
- *
- * @throws UnsupportedEncodingException
- */
- public static AutoUpdateCertificatesVerifier getVerifier() throws FileNotFoundException {
- //不需要传入微信支付证书了
- if (verifier == null) {
- verifier = new AutoUpdateCertificatesVerifier(
- new WechatPay2Credentials(TK_MCHID, new PrivateKeySigner(DIRECT_CERT_SERIAL_NO, getPrivateKey())),
- DIRECT_V3_Key.getBytes(StandardCharsets.UTF_8));
- }
- return verifier;
- }
-
-
- /**
- * 生成随机字符串
- *
- * @return
- */
- public static String createNonceStr() {
- return UUID.randomUUID().toString().replace("-", "");
- }
-}
+package com.ccsens.wechatutil.payutil;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.ccsens.wechatutil.exception.PayException;
+import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
+import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
+import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
+import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
+import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
+import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.util.EntityUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.*;
+import java.math.BigInteger;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.util.Base64;
+import java.util.UUID;
+
+/**
+ * 微信直连商户支付
+ * @author :mr.zhangsan
+ * @date :Created in 2021/6/18 23:58
+ * @version v1.0:
+ */
+@Slf4j
+public class WxPayDirectUtils {
+
+ //商户支付URL
+ private static final String URL_TRANSACTIONS
+ = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
+ //测试小程序号appid
+ public static final String TK_APPID = "wxa26bb3e3f1d2d998";
+ //测试商户号
+ public static final String TK_MCHID = "1603930405";
+ //测试小程序秘钥secret
+ public static final String TK_SECRET = "162cc6eb70bc341bc67fea210796be21";
+ //商户私钥
+ private static PrivateKey privateKey;
+ //版本>=0.1.5可使用 AutoUpdateCertificatesVerifier 类替代默认的验签器。
+ // 它会在构造时自动下载商户对应的微信支付平台证书,并每隔一段时间(默认为1个小时)更新证书。
+ private static AutoUpdateCertificatesVerifier verifier = null;
+ //WechatPayHttpClient
+ private static HttpClient httpClient = null;
+ //测试商户证书存放路径
+ private static final String Client_Key_Path = "C:\\home\\fxxt\\cert_tk\\apiclient_key.pem";
+ //测试商户v3key
+ private static final String DIRECT_V3_Key = "5IDIy173oyjSGPZHuP0lc2V3UqFBO55M";
+ //测试证书序列号
+ private static final String DIRECT_CERT_SERIAL_NO = "368344414C13EA2ABF3A59A8CF3F31E99ACE0058";
+
+
+ /**
+ * 支付订单状态
+ */
+ public enum PayOrderStatus {
+ SUCCESS, NOTPAY, CLOSED, REVOKED, USERPAYING, PAYERROR, FAILED, UNKNOWN
+ }
+
+
+ /**
+ * 商户统一下单支付
+ *
+ * 应用ID appid string[1,32] 是 body 由微信生成的应用ID,全局唯一。请求基础下单接口时请注意APPID的应用属性,例如公众号场景下,需使用应用属性为公众号的APPID
+ * 示例值:wxd678efh567hg6787
+ * 直连商户号 mchid string[1,32] 是 body 直连商户的商户号,由微信支付生成并下发。
+ * 示例值:1230000109
+ * 商品描述 description string[1,127] 是 body 商品描述
+ * 示例值:Image形象店-深圳腾大-QQ公仔
+ * 商户订单号 out_trade_no string[6,32] 是 body 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
+ * 示例值:1217752501201407033233368018
+ * 交易结束时间 time_expire string[1,64] 否 body 订单失效时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
+ * 示例值:2018-06-08T10:34:56+08:00
+ * 附加数据 attach string[1,128] 否 body 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用
+ * 示例值:自定义数据
+ * 通知地址 notify_url string[1,256] 是
+ */
+ public static JSONObject transactions(String openid, String outTradeNo, String description, String notifyUrl, int totalFee) throws Exception {
+ HttpPost httpPost = new HttpPost(URL_TRANSACTIONS);
+ httpPost.addHeader("Accept", "application/json");
+ httpPost.addHeader("Content-type", "application/json; charset=utf-8");
+
+ JSONObject params = new JSONObject();
+ JSONObject amount = new JSONObject();
+ JSONObject payer = new JSONObject();
+ payer.put("openid", openid);
+
+ amount.put("total", totalFee);
+ amount.put("currency", "CNY");
+
+ params.put("appid", TK_APPID);
+ params.put("mchid", TK_MCHID);
+ params.put("out_trade_no", outTradeNo);
+ params.put("description", description);
+ params.put("notify_url", notifyUrl);
+ params.put("amount", amount);
+ params.put("payer", payer);
+
+ httpPost.setEntity(new StringEntity(params.toJSONString(), "UTF-8"));
+ CloseableHttpResponse response = (CloseableHttpResponse) getWechatPayHttpClient().execute(httpPost);
+ String bodyAsString = EntityUtils.toString(response.getEntity());
+ JSONObject respJson = JSONObject.parseObject(bodyAsString);
+
+ Object prepayId = respJson.get("prepay_id");
+ Object code = respJson.get("code");
+
+ if (code != null) {
+ throw new Exception(respJson.get("message").toString());
+ }
+ JSONObject result = new JSONObject();
+ //根据返回的prepay_id生成发起支付需要的参数签名返回前端
+
+ result.put("appId", TK_APPID);
+ result.put("timeStamp", System.currentTimeMillis() / 1000);
+ result.put("nonceStr", createNonceStr());
+ result.put("package", "prepay_id=" + prepayId);
+ result.put("signType", "RSA");
+
+ String message = TK_APPID + "\n"
+ + result.get("timeStamp") + "\n"
+ + result.get("nonceStr") + "\n"
+ + result.get("package") + "\n";
+ String sign = wxPayReqSign(message.getBytes("utf-8"));
+ result.put("paySign", sign);
+ return result;
+ }
+
+ /**
+ * 解析支付完毕微信通知参数
+ *
+ * signature 头部签名 Wechatpay-Signature
+ * body json消息
+ * @return
+ * @throws IOException 参数名 变量 类型[长度限制] 必填 描述
+ */
+ public static JSONObject rechargeResult(HttpServletRequest request) throws Exception {
+ log.info("解析支付完毕微信通知参数");
+ //一、验证签名
+ //1.1获取平台证书
+ getVerifier();
+ //1.2检查平台证书序列号
+ String wepaySerial = request.getHeader("Wechatpay-Serial");
+ if (wepaySerial == null) {
+ throw new PayException(-9, "平台证书序列号为空");
+ }
+ log.info("获取平台证书序列号");
+ //获取平台证书序列号
+ BigInteger currentSerial = getVerifier().getValidCertificate().getSerialNumber();
+ if (StrUtil.isEmpty(wepaySerial) || !wepaySerial.equalsIgnoreCase(currentSerial.toString(16))) {
+ throw new PayException(-9, "证书序列号不一致");
+ }
+ log.info("3构造验签名串");
+ //1.3构造验签名串
+ String wepayNonce = request.getHeader("Wechatpay-Nonce");
+ String wepayTimestamp = request.getHeader("Wechatpay-Timestamp");
+ String wepayBody = null;
+ BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
+ String line = null;
+ StringBuilder body = new StringBuilder();
+ while ((line = br.readLine()) != null) {
+ body.append(line);
+ }
+ if (StrUtil.isEmpty(body.toString())) {
+ throw new PayException(-9, "body is null");
+ }
+ wepayBody = body.toString();
+
+
+ String message = wepayTimestamp + "\n"
+ + wepayNonce + "\n"
+ + body.toString() + "\n";
+ log.info("获取应答签名");
+ //1.4获取应答签名
+ String wepySignature = request.getHeader("Wechatpay-Signature");
+
+ //1.5验证签名
+ boolean rr = getVerifier().verify(wepaySerial,
+ message.getBytes(StandardCharsets.UTF_8),wepySignature);
+ if (!rr){
+ //TODO 签名验证失败抛异常
+ }
+// String sign = wxPayRespSign(message.getBytes("utf-8"));
+// if (!wepySignature.equals(sign)) {
+// throw new PayException(-9, "验证签名不一致");
+// }
+ log.info("解密数据");
+ //二、解密数据
+ JSONObject jsonObject = JSONObject.parseObject(wepayBody);
+ JSONObject resource = (JSONObject) jsonObject.get("resource");
+ AesUtil aesUtil = new AesUtil(DIRECT_V3_Key.getBytes("utf-8"));
+ //解密
+ String decryptToString = aesUtil.decryptToString(
+ resource.get("associated_data").toString().getBytes(),
+ resource.get("nonce").toString().getBytes(),
+ resource.get("ciphertext").toString());
+ JSONObject parseObject = JSONObject.parseObject(decryptToString);
+ return parseObject;
+ }
+
+ private static PayOrderStatus getPayOrderStatus(URIBuilder uriBuilder) throws URISyntaxException, IOException {
+ HttpGet httpGet = new HttpGet(uriBuilder.build());
+ httpGet.addHeader("Accept", "application/json");
+
+ CloseableHttpResponse response = (CloseableHttpResponse) getWechatPayHttpClient().execute(httpGet);
+
+ String bodyAsString = EntityUtils.toString(response.getEntity());
+
+ JSONObject jsonObject = JSONObject.parseObject(bodyAsString);
+ log.info("json:{}", jsonObject);
+ Object trade_state = jsonObject.get("trade_state");
+ if (trade_state != null) {
+ String tradeState = trade_state.toString();
+ log.info("PayOrderStatus:{}",tradeState);
+ if ("SUCCESS".equals(tradeState)) {
+ return PayOrderStatus.SUCCESS;
+ } else if ("USERPAYING".equals(tradeState)) {
+ return PayOrderStatus.USERPAYING;
+ } else {
+ return PayOrderStatus.FAILED;
+ }
+ }
+ return PayOrderStatus.UNKNOWN;
+ }
+
+ /**
+ * 商户订单号查询
+ *
+ * @param transactionId 微信订单号
+ * @return
+ * @throws IOException
+ * @throws URISyntaxException
+ */
+ public static PayOrderStatus wechatOrder(String transactionId) throws IOException, URISyntaxException {
+ URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + transactionId + "?mchid=" + TK_MCHID);
+ return getPayOrderStatus(uriBuilder);
+ }
+
+ /**
+ * 根据商户证书,获取私钥
+ *
+ * @return
+ * @throws FileNotFoundException
+ */
+ public static PrivateKey getPrivateKey() throws FileNotFoundException {
+ if (privateKey == null) {
+ privateKey = PemUtil.loadPrivateKey(
+ new FileInputStream(Client_Key_Path));
+ }
+ return privateKey;
+ }
+
+ /**
+ * 依据商户证书私钥进行签名
+ *
+ * @param message
+ * @return
+ * @throws Exception
+ */
+ public static String wxPayReqSign(byte[] message) throws Exception {
+ Signature sign = Signature.getInstance("SHA256withRSA");
+ sign.initSign(getPrivateKey());
+ sign.update(message);
+
+ return Base64.getEncoder().encodeToString(sign.sign());
+ }
+
+ /**
+ * 根据微信平台证书获取httpclient
+ *
+ * @return
+ * @throws FileNotFoundException
+ * @throws UnsupportedEncodingException
+ */
+ public static HttpClient getWechatPayHttpClient() throws FileNotFoundException, UnsupportedEncodingException {
+ if (httpClient == null) {
+ //构造WechatPayHttpClientBuilder
+ WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
+ .withMerchant(TK_MCHID, DIRECT_CERT_SERIAL_NO, getPrivateKey())
+ .withValidator(new WechatPay2Validator(getVerifier()));
+
+ // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
+ httpClient = builder.build();
+ }
+ return httpClient;
+ }
+
+ /**
+ * 自动获取微信平台证书
+ *
+ * @throws UnsupportedEncodingException
+ */
+ public static AutoUpdateCertificatesVerifier getVerifier() throws FileNotFoundException {
+ //不需要传入微信支付证书了
+ if (verifier == null) {
+ verifier = new AutoUpdateCertificatesVerifier(
+ new WechatPay2Credentials(TK_MCHID, new PrivateKeySigner(DIRECT_CERT_SERIAL_NO, getPrivateKey())),
+ DIRECT_V3_Key.getBytes(StandardCharsets.UTF_8));
+ }
+ return verifier;
+ }
+
+
+ /**
+ * 生成随机字符串
+ *
+ * @return
+ */
+ public static String createNonceStr() {
+ return UUID.randomUUID().toString().replace("-", "");
+ }
+}
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/payutil/WxPayProviderUtils.java b/util_wechat/src/main/java/com/ccsens/wechatutil/payutil/WxPayProviderUtils.java
similarity index 97%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/payutil/WxPayProviderUtils.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/payutil/WxPayProviderUtils.java
index 908f21f..6fe155d 100644
--- a/wechatutil/src/main/java/com/ccsens/wechatutil/payutil/WxPayProviderUtils.java
+++ b/util_wechat/src/main/java/com/ccsens/wechatutil/payutil/WxPayProviderUtils.java
@@ -1,687 +1,687 @@
-package com.ccsens.wechatutil.payutil;
-
-import cn.hutool.core.util.StrUtil;
-import com.alibaba.fastjson.JSONObject;
-import com.ccsens.util.HttpsUtil;
-import com.ccsens.wechatutil.exception.PayException;
-import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
-import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
-import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
-import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
-import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
-import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.utils.URIBuilder;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.util.EntityUtils;
-import javax.servlet.http.HttpServletRequest;
-import java.io.*;
-import java.math.BigInteger;
-import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
-import java.security.PrivateKey;
-import java.security.Signature;
-import java.util.*;
-
-/**
- * 微信服务商支付
- * @author :mr.zhangsan
- * @date :Created in 2021/5/15 22:24
- * @version v1.0:
- */
-@Slf4j
-public class WxPayProviderUtils {
-
- /**
- * 支付订单状态
- */
- public enum PayOrderStatus {
- SUCCESS, NOTPAY, CLOSED, REVOKED, USERPAYING, PAYERROR, FAILED, UNKNOWN
- }
-
- private static final String URL_MERCHANT_PAY
- = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi";
- //退款url
- private static final String URL_REFUND_PAY
- = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
- //查询退款url
- private static final String SEL_URL_REFUND_PAY
- = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
- //付款到零钱url
- private static final String URL_PAYTO_USER
- = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
- //商户支付URL
- private static final String URL_TRANSACTIONS
- = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
- //测试小程序APPID
- private static final String appid = "wxf30402e727f0840a";
- //测试小程序secret
- private static final String secret = "70402290ac83857c7324b0ee881b544a";
- //商户支付
- //服务商API秘钥key
- private static final String KEY = "5a689a2d6b8c4ff499c23d998fde0941";
- // 服务商应用ID(公众号appid)
- private static final String SPAPPID = "wx65d45856040e9a4a";
- // 服务商户号
- private static final String SPMECHID = "1610985721";
- //子商户应用ID
- private static final String SUBAPPID = appid;
- // 子商户号
- private static final String SUBMCHID = "1611259929";
- //服务商证书序列号
- private static final String CERT_SERIAL_NO = "1251E728C5B765190B641C9B45B2A18A4DDEC553";
- //微信提现url
- private static final String URL_PAY_TO_USR_WX
- = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
- //服务商证书存放路径
- private static final String Client_Key_Path = "C:\\home\\fxxt\\cert_fws\\apiclient_key.pem";
- //服务商APIv3Key
- private static final String API_V3_Key = "gRcJ8bpi5imIm4qbbRch5iSSD77DFCKY";
- //测试商户证书存放路径
- public static final String PATH_WX_CRET = "C:\\home\\fxxt\\cert_zyc\\apiclient_key.pem";
- //测试商户私钥
- private static PrivateKey privateKey;
- //版本>=0.1.5可使用 AutoUpdateCertificatesVerifier 类替代默认的验签器。
- // 它会在构造时自动下载商户对应的微信支付平台证书,并每隔一段时间(默认为1个小时)更新证书。
- private static AutoUpdateCertificatesVerifier verifier = null;
- //WechatPayHttpClient
- private static HttpClient httpClient = null;
- //加密方式
- private static final String schema = "WECHATPAY2-SHA256-RSA2048";
-
- /**
- * 私有构造 不允许生成实例, 只允许调用静态方法
- */
- private WxPayProviderUtils() {
-
- }
-
- /**
- * 生成随机字符串
- *
- * @return
- */
- public static String createNonceStr() {
- return UUID.randomUUID().toString().replace("-", "");
- }
-
-
- /**
- * 依据商户证书私钥进行签名
- *
- * @param message
- * @return
- * @throws Exception
- */
- private static String wxPayReqSign(byte[] message) throws Exception {
- Signature sign = Signature.getInstance("SHA256withRSA");
- sign.initSign(getPrivateKey());
- sign.update(message);
-
- return Base64.getEncoder().encodeToString(sign.sign());
- }
-
- /**
- * 依据微信支付平台证书(公钥)进行签名
- *
- * @param message
- * @return
- * @throws Exception
- */
- private static boolean wxPayRespSign(byte[] message,String signature) throws Exception {
- Signature sign = Signature.getInstance("SHA256withRSA");
- sign.initVerify(getVerifier().getValidCertificate());
- sign.update(message);
- return sign.verify(Base64.getDecoder().decode(signature));
- }
-
- /**
- * 根据商户证书,获取私钥
- *
- * @return
- * @throws FileNotFoundException
- */
- public static PrivateKey getPrivateKey() throws FileNotFoundException {
- if (privateKey == null) {
- privateKey = PemUtil.loadPrivateKey(
- new FileInputStream(Client_Key_Path));
- }
- return privateKey;
- }
-
- /**
- * 自动获取微信平台证书
- *
- * @throws UnsupportedEncodingException
- */
- public static AutoUpdateCertificatesVerifier getVerifier() throws FileNotFoundException {
- //不需要传入微信支付证书了
- if (verifier == null) {
- verifier = new AutoUpdateCertificatesVerifier(
- new WechatPay2Credentials(SPMECHID, new PrivateKeySigner(CERT_SERIAL_NO, getPrivateKey())),
- API_V3_Key.getBytes(StandardCharsets.UTF_8));
- }
- return verifier;
- }
-
- /**
- * 根据微信平台证书获取httpclient
- *
- * @return
- * @throws FileNotFoundException
- * @throws UnsupportedEncodingException
- */
- public static HttpClient getWechatPayHttpClient() throws FileNotFoundException, UnsupportedEncodingException {
- if (httpClient == null) {
- //构造WechatPayHttpClientBuilder
- WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
- .withMerchant(SPMECHID, CERT_SERIAL_NO, getPrivateKey())
- .withValidator(new WechatPay2Validator(getVerifier()));
-
- // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
- httpClient = builder.build();
- }
- return httpClient;
- }
-
- /**
- * 服务商统一下单支付
- */
- public static JSONObject merchantPreparyPay(String openid, String outTradeNo, String description, String notifyUrl, int totalFee) throws Exception {
- HttpPost httpPost = new HttpPost(URL_MERCHANT_PAY);
- httpPost.addHeader("Accept", "application/json");
- httpPost.addHeader("Content-type", "application/json; charset=utf-8");
-
- JSONObject params = new JSONObject();
- JSONObject amount = new JSONObject();
- JSONObject payer = new JSONObject();
- payer.put("sub_openid", openid);
-
- amount.put("total", totalFee);
- amount.put("currency", "CNY");
-
- params.put("sp_mchid", SPMECHID);
- params.put("sub_mchid", SUBMCHID);
- log.info("out_trade_no:{}", outTradeNo);
- params.put("out_trade_no", outTradeNo);
- params.put("sp_appid", SPAPPID);
- params.put("sub_appid", SUBAPPID);
- params.put("description", description);
- params.put("notify_url", notifyUrl);
- params.put("amount", amount);
- params.put("payer", payer);
-
- httpPost.setEntity(new StringEntity(params.toJSONString(), "UTF-8"));
- CloseableHttpResponse response = (CloseableHttpResponse) getWechatPayHttpClient().execute(httpPost);
- String bodyAsString = EntityUtils.toString(response.getEntity());
- JSONObject respJson = JSONObject.parseObject(bodyAsString);
- Object prepayId = respJson.get("prepay_id");
- Object code = respJson.get("code");
-
- if (code != null) {
- throw new Exception(respJson.get("message").toString());
- }
- JSONObject result = new JSONObject();
- //根据返回的prepay_id生成发起支付需要的参数签名返回前端
-
- result.put("appId", SUBAPPID);
- result.put("timeStamp", System.currentTimeMillis() / 1000);
- result.put("nonceStr", createNonceStr());
- result.put("package", "prepay_id=" + prepayId);
- result.put("signType", "RSA");
-
- log.info("准备签名");
- String message = SUBAPPID + "\n"
- + result.get("timeStamp") + "\n"
- + result.get("nonceStr") + "\n"
- + result.get("package") + "\n";
- String sign = wxPayReqSign(message.getBytes(StandardCharsets.UTF_8));
- log.info("sign:{}", sign);
- result.put("paySign", sign);
- return result;
- }
-
- /**
- * 解析支付完毕微信通知参数
- *
- * signature 头部签名 Wechatpay-Signature
- * body json消息
- *
- * @return
- * @throws IOException 参数名 变量 类型[长度限制] 必填 描述
- */
- public JSONObject rechargeResult(HttpServletRequest request) throws Exception {
- //一、验证签名
- //1.1获取平台证书
- getVerifier();
- //1.2检查平台证书序列号
- String wepaySerial = request.getHeader("Wechatpay-Serial");
- if (wepaySerial == null) {
- throw new PayException(-9, "平台证书序列号为空");
- }
- //获取平台证书序列号
- BigInteger currentSerial = getVerifier().getValidCertificate().getSerialNumber();
- log.info("currentSerial:{} " + currentSerial.toString(16));
- log.info("wepaySerial:{} " + wepaySerial);
- if (StrUtil.isEmpty(wepaySerial) || !wepaySerial.equalsIgnoreCase(currentSerial.toString(16))) {
- throw new PayException(-9, "证书序列号不一致");
- }
- //1.3构造验签名串
- String wepayNonce = request.getHeader("Wechatpay-Nonce");
- String wepayTimestamp = request.getHeader("Wechatpay-Timestamp");
- String wepayBody = null;
- BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
- String line = null;
- StringBuilder body = new StringBuilder();
- while ((line = br.readLine()) != null) {
- body.append(line);
- }
- if (StrUtil.isEmpty(body.toString())) {
- throw new PayException(-9, "body is null");
- }
- wepayBody = body.toString();
-
- String message = wepayTimestamp + "\n"
- + wepayNonce + "\n"
- + body.toString() + "\n";
- //1.4获取应答签名
- String wepySignature = request.getHeader("Wechatpay-Signature");
- log.info("----------------1,{}\n----{}", wepySignature, message);
-
-
- //1.5验证签名
- boolean rr = getVerifier().verify(wepaySerial,
- message.getBytes(StandardCharsets.UTF_8), wepySignature);
-
-// boolean rr = wxPayRespSign(message.getBytes("utf-8"), wepySignature);
- if (!rr) {
- //TODO 签名验证失败抛异常
- throw new PayException(-9, "验证签名不一致");
- }
- log.info("+++++++++++zzc 签名调用+++++++++++++++++++++ ");
- //二、解密数据
- JSONObject jsonObject = JSONObject.parseObject(wepayBody);
- JSONObject resource = (JSONObject) jsonObject.get("resource");
- AesUtil aesUtil = new AesUtil(API_V3_Key.getBytes("utf-8"));
- //解密
- String decryptToString = aesUtil.decryptToString(
- resource.get("associated_data").toString().getBytes(),
- resource.get("nonce").toString().getBytes(),
- resource.get("ciphertext").toString());
- JSONObject parseObject = JSONObject.parseObject(decryptToString);
- return parseObject;
- }
-
- private static PayOrderStatus getPayOrderStatus(URIBuilder uriBuilder) throws URISyntaxException, IOException {
- HttpGet httpGet = new HttpGet(uriBuilder.build());
- httpGet.addHeader("Accept", "application/json");
-
- CloseableHttpResponse response = (CloseableHttpResponse) getWechatPayHttpClient().execute(httpGet);
-
- String bodyAsString = EntityUtils.toString(response.getEntity());
-
- JSONObject jsonObject = JSONObject.parseObject(bodyAsString);
- log.info("json:{}", jsonObject);
- Object trade_state = jsonObject.get("trade_state");
- if (trade_state != null) {
- String tradeState = trade_state.toString();
- if ("SUCCESS".equals(tradeState)) {
- return PayOrderStatus.SUCCESS;
- } else if ("USERPAYING".equals(tradeState)) {
- return PayOrderStatus.USERPAYING;
- } else {
- return PayOrderStatus.FAILED;
- }
- }
- return PayOrderStatus.UNKNOWN;
- }
-
- /**
- * 服务商查询订单
- *
- * @param orderNo
- * @throws Exception
- */
- public static PayOrderStatus queryOrder(String orderNo) throws IOException, URISyntaxException {
- URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/id/" + orderNo + "?sp_mchid=" + SPMECHID + "&sub_mchid=" + SUBMCHID);
- return getPayOrderStatus(uriBuilder);
- }
-
- /**
- * 商户订单号查询
- *
- * @param transactionId 微信订单号
- * @return
- * @throws IOException
- * @throws URISyntaxException
- */
- public static PayOrderStatus wechatOrder(String transactionId) throws IOException, URISyntaxException {
- URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/out-trade-no/" + transactionId + "?sp_mchid=" + SPMECHID + "&sub_mchid=" + SUBMCHID);
- return getPayOrderStatus(uriBuilder);
- }
-
-
- /**
- * 服务商关闭订单
- *
- * @param orderNo 商户订单号
- */
- public static void closeOrder(String orderNo) throws IOException {
- HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/out-trade-no/" + orderNo + "/close");
- httpPost.addHeader("Accept", "application/json");
- httpPost.addHeader("Content-type", "application/json; charset=utf-8");
-
- JSONObject params = new JSONObject();
- params.put("sp_mchid", SPMECHID);
- params.put("sub_mchid", SUBMCHID);
-
- httpPost.setEntity(new StringEntity(params.toJSONString(), "UTF-8"));
- getWechatPayHttpClient().execute(httpPost);
- //接口响应204,无内容
- }
-
-
- /**
- * 服务商退款
- *
- * @param refund 退款金额
- * @param outTradeNo 商户订单号
- * @param outRefundNo 商户退款单号
- * @param notifyUrl 退款回调url
- * @param total 原订单金额
- * @return
- * @throws Exception
- */
- public static String refunds(int refund, String outTradeNo, String outRefundNo, String notifyUrl, int total) throws Exception {
- HttpPost httpPost = new HttpPost(URL_REFUND_PAY);
- httpPost.addHeader("Accept", "application/json");
- httpPost.addHeader("Content-type", "application/json; charset=utf-8");
-
- JSONObject params = new JSONObject();
- JSONObject amount = new JSONObject();
-
- //金额信息
- amount.put("refund", refund);
- //原订单金额
- amount.put("total", total);
- //退款币种
- amount.put("currency", "CNY");
- //子商户号 否
- params.put("sub_mchid", SUBMCHID);
-//// 微信支付订单号 (二选一)
-// params.put("transaction_id", SUBMCHID);
- //商户订单号 (二选一)
- params.put("out_trade_no", outTradeNo);
- //商户退款单号
- log.info("商户退款单号----------------------------------------out_trade_no:{}", outRefundNo);
- params.put("out_refund_no", outRefundNo);
- //退款结果回调url 否
- params.put("notify_url", notifyUrl);
- //金额信息
- params.put("amount", amount);
-
- httpPost.setEntity(new StringEntity(params.toJSONString(), "UTF-8"));
- CloseableHttpResponse response = (CloseableHttpResponse) getWechatPayHttpClient().execute(httpPost);
- String bodyAsString = EntityUtils.toString(response.getEntity());
- JSONObject respJson = JSONObject.parseObject(bodyAsString);
-
- log.info("respJson:{}", respJson);
- Object result = respJson.get("status");
- String status = result.toString();
- if ("SUCCESS".equals(status) || "PROCESSING".equals(status)) {
- return status;
- } else {
- throw new PayException("[" + respJson.get("err_code") + "]"
- + respJson.get("err_code_des"));
- }
- }
-
- /**
- * 查询单笔退款
- */
- public static JSONObject selRechargeResult(String out_refund_no) throws Exception {
- HttpGet httpGet = new HttpGet(SEL_URL_REFUND_PAY + "/" + out_refund_no + "?sub_mchid=" + SUBMCHID);
- httpGet.addHeader("Accept", "application/json");
- httpGet.addHeader("Content-type", "application/json; charset=utf-8");
- httpGet.addHeader("Wechatpay-Serial", getVerifier().getValidCertificate().getSerialNumber().toString(16));
-
- CloseableHttpResponse response = (CloseableHttpResponse) getWechatPayHttpClient().execute(httpGet);
- String bodyAsString = EntityUtils.toString(response.getEntity());
- return JSONObject.parseObject(bodyAsString);
- }
-
- /**
- * 微信退款结果通知
- */
- public static JSONObject tuiKuanResult(HttpServletRequest request) throws Exception {
- //一、验证签名
- //1.1获取平台证书
- getVerifier();
- //1.2检查平台证书序列号
- String wepaySerial = request.getHeader("Wechatpay-Serial");
- if (wepaySerial == null) {
- throw new PayException(-9, "平台证书序列号为空");
- }
- //获取平台证书序列号
- BigInteger currentSerial = getVerifier().getValidCertificate().getSerialNumber();
- if (StrUtil.isEmpty(wepaySerial) || !wepaySerial.equalsIgnoreCase(currentSerial.toString(16))) {
- throw new PayException(-9, "证书序列号不一致");
- }
- String wepayNonce = request.getHeader("Wechatpay-Nonce");
- String wepayTimestamp = request.getHeader("Wechatpay-Timestamp");
- String wepayBody = null;
- BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(),StandardCharsets.UTF_8));
- String line = null;
- StringBuilder body = new StringBuilder();
- while ((line = br.readLine()) != null) {
- body.append(line);
- }
- if (StrUtil.isEmpty(body.toString())) {
- throw new PayException(-9, "body is null");
- }
- wepayBody = body.toString();
-
- String message = wepayTimestamp + "\n"
- + wepayNonce + "\n"
- + body.toString() + "\n";
- //1.4获取应答签名
- String wepySignature = request.getHeader("Wechatpay-Signature");
-
- //1.5验证签名
- boolean rr = getVerifier().verify(wepaySerial,
- message.getBytes(StandardCharsets.UTF_8),wepySignature);
- if (!rr){
- }
- JSONObject jsonObject = JSONObject.parseObject(wepayBody);
- JSONObject resource = (JSONObject) jsonObject.get("resource");
- AesUtil aesUtil = new AesUtil(API_V3_Key.getBytes("utf-8"));
- //解密
- String decryptToString = aesUtil.decryptToString(
- resource.get("associated_data").toString().getBytes(),//附加数据
- resource.get("nonce").toString().getBytes(),//随机串
- resource.get("ciphertext").toString());//数据密文
- JSONObject parseObject = JSONObject.parseObject(decryptToString);
- return parseObject;
- }
-
-
- /**
- * 企业付款到零钱
- *
- * @param partner_trade_no 商户订单号
- * @param openid 用户openid
- * @param total_fee 金额
- * @param desc 付款备注
- * @param spbill_create_ip Ip地址
- * @return
- * @throws Exception
- */
- public static Map payToUsrWx(
- String partner_trade_no, String openid, int total_fee, String desc, String spbill_create_ip)
- throws Exception {
- //1.构造请求字符串
- Map reqMap = new HashMap();
- reqMap.put("mch_appid", SUBAPPID);
- reqMap.put("mchid", SUBMCHID);
- //reqMap.put("device_info",null); //不能添加空字段,Jackson会生成闭包xml 导致签名失败
- reqMap.put("nonce_str", createNonceStr());
- reqMap.put("partner_trade_no", partner_trade_no);
- reqMap.put("openid", openid);
- reqMap.put("check_name", "NO_CHECK");
- //reqMap.put("re_user_name",null);
- reqMap.put("amount", total_fee + "");
- reqMap.put("desc", desc);
- reqMap.put("spbill_create_ip", spbill_create_ip);
- reqMap.put("sign", createSign(reqMap));
-
- //2.发送付款请求
- String reqrXml = JacksonUtil.mapToXml(paraFilterEmpty(reqMap), "xml");
- String respXml = HttpsUtil.httpsRequest(URL_PAY_TO_USR_WX, "POST", reqrXml,
- PATH_WX_CRET, SUBMCHID);
- System.out.println("---------------PayToUsrWx Request Xml-----------------");
- System.out.println(reqrXml);
- System.out.println("---------------PayToUsrWx Response Xml-----------------");
- System.out.println(respXml);
- System.out.println("---------------PayToUsrWx end-----------------");
-
- //3.判断成功失败
- Map respMap = JacksonUtil.xmlToMap(new ByteArrayInputStream(respXml.getBytes(StandardCharsets.UTF_8)));
- String return_code, result_code;
- return_code = String.valueOf(respMap.get("return_code"));
- result_code = String.valueOf(respMap.get("result_code"));
-
- if (!StrUtil.isEmpty(return_code) && !StrUtil.isEmpty(result_code)) {
- if (return_code.equals("SUCCESS") && return_code.equals(result_code)) {
- return respMap;
- } else {
- throw new PayException("[" + respMap.get("err_code") + "]"
- + respMap.get("err_code_des"));
- }
- } else {
- throw new PayException(String.valueOf(respMap.get("return_msg")));
- }
- //return null;
- }
-
- /**
- * Create Sign
- *
- * @param sParaTemp
- * @return
- */
- private static String createSign(Map sParaTemp) throws FileNotFoundException {
- // 除去数组中的空值和签名参数
- Map sPara = paraFilter(sParaTemp);
- String prestr = createLinkString(sPara); // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
- //MD5运算生成签名
- String sign = sign(prestr, getPrivateKey().toString(), "utf-8").toUpperCase();
-// return sign;
- return sign;
- }
-
- /**
- * 签名字符串
- *
- * @param text 需要签名的字符串
- * @param key 密钥
- * @param input_charset 编码格式
- * @return 签名结果
- */
- private static String sign(String text, String key, String input_charset) {
- text = text + "&key=" + key;
- return DigestUtils.md5Hex(getContentBytes(text, input_charset));
- }
-
- /**
- * @param content
- * @param charset
- * @return
- * @throws
- * @throws UnsupportedEncodingException
- */
- private static byte[] getContentBytes(String content, String charset) {
- if (charset == null || "".equals(charset)) {
- return content.getBytes();
- }
- try {
- return content.getBytes(charset);
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
- }
- }
-
- /**
- * 除去数组中的空值和签名参数
- *
- * @param sArray 签名参数组
- * @return 去掉空值与签名参数后的新签名参数组
- */
- private static Map paraFilter(Map sArray) {
- Map result = new HashMap();
- if (sArray == null || sArray.size() <= 0) {
- return result;
- }
- for (String key : sArray.keySet()) {
- Object objVal = sArray.get(key);
- if (objVal == null) {
- continue;
- }
- String value = String.valueOf(objVal);
- if (StrUtil.isEmpty(value) || key.equalsIgnoreCase("sign") || key.equalsIgnoreCase("sign_type")) {
- continue;
- }
- result.put(key, value);
- }
- return result;
- }
-
- /**
- * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
- *
- * @param params 需要排序并参与字符拼接的参数组
- * @return 拼接后字符串
- */
- private static String createLinkString(Map params) {
- List keys = new ArrayList(params.keySet());
- Collections.sort(keys);
- String prestr = "";
- for (int i = 0; i < keys.size(); i++) {
- String key = keys.get(i);
- String value = params.get(key);
- if (i == keys.size() - 1) {// 拼接时,不包括最后一个&字符
- prestr = prestr + key + "=" + value;
- } else {
- prestr = prestr + key + "=" + value + "&";
- }
- }
- return prestr;
- }
-
-
- /**
- * 除去数组中的空值和签名参数
- *
- * @param sArray 签名参数组
- * @return 去掉空值与签名参数后的新签名参数组
- */
- private static Map paraFilterEmpty(Map sArray) {
- Map result = new HashMap();
- if (sArray == null || sArray.size() <= 0) {
- return result;
- }
- for (String key : sArray.keySet()) {
- Object objVal = sArray.get(key);
- if (objVal == null) {
- continue;
- }
- String value = String.valueOf(objVal);
- result.put(key, value);
- }
- return result;
- }
+package com.ccsens.wechatutil.payutil;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.ccsens.util.HttpsUtil;
+import com.ccsens.wechatutil.exception.PayException;
+import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
+import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
+import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
+import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
+import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
+import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.util.EntityUtils;
+import javax.servlet.http.HttpServletRequest;
+import java.io.*;
+import java.math.BigInteger;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.util.*;
+
+/**
+ * 微信服务商支付
+ * @author :mr.zhangsan
+ * @date :Created in 2021/5/15 22:24
+ * @version v1.0:
+ */
+@Slf4j
+public class WxPayProviderUtils {
+
+ /**
+ * 支付订单状态
+ */
+ public enum PayOrderStatus {
+ SUCCESS, NOTPAY, CLOSED, REVOKED, USERPAYING, PAYERROR, FAILED, UNKNOWN
+ }
+
+ private static final String URL_MERCHANT_PAY
+ = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi";
+ //退款url
+ private static final String URL_REFUND_PAY
+ = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
+ //查询退款url
+ private static final String SEL_URL_REFUND_PAY
+ = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
+ //付款到零钱url
+ private static final String URL_PAYTO_USER
+ = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
+ //商户支付URL
+ private static final String URL_TRANSACTIONS
+ = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
+ //测试小程序APPID
+ private static final String appid = "wxf30402e727f0840a";
+ //测试小程序secret
+ private static final String secret = "70402290ac83857c7324b0ee881b544a";
+ //商户支付
+ //服务商API秘钥key
+ private static final String KEY = "5a689a2d6b8c4ff499c23d998fde0941";
+ // 服务商应用ID(公众号appid)
+ private static final String SPAPPID = "wx65d45856040e9a4a";
+ // 服务商户号
+ private static final String SPMECHID = "1610985721";
+ //子商户应用ID
+ private static final String SUBAPPID = appid;
+ // 子商户号
+ private static final String SUBMCHID = "1611259929";
+ //服务商证书序列号
+ private static final String CERT_SERIAL_NO = "1251E728C5B765190B641C9B45B2A18A4DDEC553";
+ //微信提现url
+ private static final String URL_PAY_TO_USR_WX
+ = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
+ //服务商证书存放路径
+ private static final String Client_Key_Path = "C:\\home\\fxxt\\cert_fws\\apiclient_key.pem";
+ //服务商APIv3Key
+ private static final String API_V3_Key = "gRcJ8bpi5imIm4qbbRch5iSSD77DFCKY";
+ //测试商户证书存放路径
+ public static final String PATH_WX_CRET = "C:\\home\\fxxt\\cert_zyc\\apiclient_key.pem";
+ //测试商户私钥
+ private static PrivateKey privateKey;
+ //版本>=0.1.5可使用 AutoUpdateCertificatesVerifier 类替代默认的验签器。
+ // 它会在构造时自动下载商户对应的微信支付平台证书,并每隔一段时间(默认为1个小时)更新证书。
+ private static AutoUpdateCertificatesVerifier verifier = null;
+ //WechatPayHttpClient
+ private static HttpClient httpClient = null;
+ //加密方式
+ private static final String schema = "WECHATPAY2-SHA256-RSA2048";
+
+ /**
+ * 私有构造 不允许生成实例, 只允许调用静态方法
+ */
+ private WxPayProviderUtils() {
+
+ }
+
+ /**
+ * 生成随机字符串
+ *
+ * @return
+ */
+ public static String createNonceStr() {
+ return UUID.randomUUID().toString().replace("-", "");
+ }
+
+
+ /**
+ * 依据商户证书私钥进行签名
+ *
+ * @param message
+ * @return
+ * @throws Exception
+ */
+ private static String wxPayReqSign(byte[] message) throws Exception {
+ Signature sign = Signature.getInstance("SHA256withRSA");
+ sign.initSign(getPrivateKey());
+ sign.update(message);
+
+ return Base64.getEncoder().encodeToString(sign.sign());
+ }
+
+ /**
+ * 依据微信支付平台证书(公钥)进行签名
+ *
+ * @param message
+ * @return
+ * @throws Exception
+ */
+ private static boolean wxPayRespSign(byte[] message,String signature) throws Exception {
+ Signature sign = Signature.getInstance("SHA256withRSA");
+ sign.initVerify(getVerifier().getValidCertificate());
+ sign.update(message);
+ return sign.verify(Base64.getDecoder().decode(signature));
+ }
+
+ /**
+ * 根据商户证书,获取私钥
+ *
+ * @return
+ * @throws FileNotFoundException
+ */
+ public static PrivateKey getPrivateKey() throws FileNotFoundException {
+ if (privateKey == null) {
+ privateKey = PemUtil.loadPrivateKey(
+ new FileInputStream(Client_Key_Path));
+ }
+ return privateKey;
+ }
+
+ /**
+ * 自动获取微信平台证书
+ *
+ * @throws UnsupportedEncodingException
+ */
+ public static AutoUpdateCertificatesVerifier getVerifier() throws FileNotFoundException {
+ //不需要传入微信支付证书了
+ if (verifier == null) {
+ verifier = new AutoUpdateCertificatesVerifier(
+ new WechatPay2Credentials(SPMECHID, new PrivateKeySigner(CERT_SERIAL_NO, getPrivateKey())),
+ API_V3_Key.getBytes(StandardCharsets.UTF_8));
+ }
+ return verifier;
+ }
+
+ /**
+ * 根据微信平台证书获取httpclient
+ *
+ * @return
+ * @throws FileNotFoundException
+ * @throws UnsupportedEncodingException
+ */
+ public static HttpClient getWechatPayHttpClient() throws FileNotFoundException, UnsupportedEncodingException {
+ if (httpClient == null) {
+ //构造WechatPayHttpClientBuilder
+ WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
+ .withMerchant(SPMECHID, CERT_SERIAL_NO, getPrivateKey())
+ .withValidator(new WechatPay2Validator(getVerifier()));
+
+ // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
+ httpClient = builder.build();
+ }
+ return httpClient;
+ }
+
+ /**
+ * 服务商统一下单支付
+ */
+ public static JSONObject merchantPreparyPay(String openid, String outTradeNo, String description, String notifyUrl, int totalFee) throws Exception {
+ HttpPost httpPost = new HttpPost(URL_MERCHANT_PAY);
+ httpPost.addHeader("Accept", "application/json");
+ httpPost.addHeader("Content-type", "application/json; charset=utf-8");
+
+ JSONObject params = new JSONObject();
+ JSONObject amount = new JSONObject();
+ JSONObject payer = new JSONObject();
+ payer.put("sub_openid", openid);
+
+ amount.put("total", totalFee);
+ amount.put("currency", "CNY");
+
+ params.put("sp_mchid", SPMECHID);
+ params.put("sub_mchid", SUBMCHID);
+ log.info("out_trade_no:{}", outTradeNo);
+ params.put("out_trade_no", outTradeNo);
+ params.put("sp_appid", SPAPPID);
+ params.put("sub_appid", SUBAPPID);
+ params.put("description", description);
+ params.put("notify_url", notifyUrl);
+ params.put("amount", amount);
+ params.put("payer", payer);
+
+ httpPost.setEntity(new StringEntity(params.toJSONString(), "UTF-8"));
+ CloseableHttpResponse response = (CloseableHttpResponse) getWechatPayHttpClient().execute(httpPost);
+ String bodyAsString = EntityUtils.toString(response.getEntity());
+ JSONObject respJson = JSONObject.parseObject(bodyAsString);
+ Object prepayId = respJson.get("prepay_id");
+ Object code = respJson.get("code");
+
+ if (code != null) {
+ throw new Exception(respJson.get("message").toString());
+ }
+ JSONObject result = new JSONObject();
+ //根据返回的prepay_id生成发起支付需要的参数签名返回前端
+
+ result.put("appId", SUBAPPID);
+ result.put("timeStamp", System.currentTimeMillis() / 1000);
+ result.put("nonceStr", createNonceStr());
+ result.put("package", "prepay_id=" + prepayId);
+ result.put("signType", "RSA");
+
+ log.info("准备签名");
+ String message = SUBAPPID + "\n"
+ + result.get("timeStamp") + "\n"
+ + result.get("nonceStr") + "\n"
+ + result.get("package") + "\n";
+ String sign = wxPayReqSign(message.getBytes(StandardCharsets.UTF_8));
+ log.info("sign:{}", sign);
+ result.put("paySign", sign);
+ return result;
+ }
+
+ /**
+ * 解析支付完毕微信通知参数
+ *
+ * signature 头部签名 Wechatpay-Signature
+ * body json消息
+ *
+ * @return
+ * @throws IOException 参数名 变量 类型[长度限制] 必填 描述
+ */
+ public JSONObject rechargeResult(HttpServletRequest request) throws Exception {
+ //一、验证签名
+ //1.1获取平台证书
+ getVerifier();
+ //1.2检查平台证书序列号
+ String wepaySerial = request.getHeader("Wechatpay-Serial");
+ if (wepaySerial == null) {
+ throw new PayException(-9, "平台证书序列号为空");
+ }
+ //获取平台证书序列号
+ BigInteger currentSerial = getVerifier().getValidCertificate().getSerialNumber();
+ log.info("currentSerial:{} " + currentSerial.toString(16));
+ log.info("wepaySerial:{} " + wepaySerial);
+ if (StrUtil.isEmpty(wepaySerial) || !wepaySerial.equalsIgnoreCase(currentSerial.toString(16))) {
+ throw new PayException(-9, "证书序列号不一致");
+ }
+ //1.3构造验签名串
+ String wepayNonce = request.getHeader("Wechatpay-Nonce");
+ String wepayTimestamp = request.getHeader("Wechatpay-Timestamp");
+ String wepayBody = null;
+ BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
+ String line = null;
+ StringBuilder body = new StringBuilder();
+ while ((line = br.readLine()) != null) {
+ body.append(line);
+ }
+ if (StrUtil.isEmpty(body.toString())) {
+ throw new PayException(-9, "body is null");
+ }
+ wepayBody = body.toString();
+
+ String message = wepayTimestamp + "\n"
+ + wepayNonce + "\n"
+ + body.toString() + "\n";
+ //1.4获取应答签名
+ String wepySignature = request.getHeader("Wechatpay-Signature");
+ log.info("----------------1,{}\n----{}", wepySignature, message);
+
+
+ //1.5验证签名
+ boolean rr = getVerifier().verify(wepaySerial,
+ message.getBytes(StandardCharsets.UTF_8), wepySignature);
+
+// boolean rr = wxPayRespSign(message.getBytes("utf-8"), wepySignature);
+ if (!rr) {
+ //TODO 签名验证失败抛异常
+ throw new PayException(-9, "验证签名不一致");
+ }
+ log.info("+++++++++++zzc 签名调用+++++++++++++++++++++ ");
+ //二、解密数据
+ JSONObject jsonObject = JSONObject.parseObject(wepayBody);
+ JSONObject resource = (JSONObject) jsonObject.get("resource");
+ AesUtil aesUtil = new AesUtil(API_V3_Key.getBytes("utf-8"));
+ //解密
+ String decryptToString = aesUtil.decryptToString(
+ resource.get("associated_data").toString().getBytes(),
+ resource.get("nonce").toString().getBytes(),
+ resource.get("ciphertext").toString());
+ JSONObject parseObject = JSONObject.parseObject(decryptToString);
+ return parseObject;
+ }
+
+ private static PayOrderStatus getPayOrderStatus(URIBuilder uriBuilder) throws URISyntaxException, IOException {
+ HttpGet httpGet = new HttpGet(uriBuilder.build());
+ httpGet.addHeader("Accept", "application/json");
+
+ CloseableHttpResponse response = (CloseableHttpResponse) getWechatPayHttpClient().execute(httpGet);
+
+ String bodyAsString = EntityUtils.toString(response.getEntity());
+
+ JSONObject jsonObject = JSONObject.parseObject(bodyAsString);
+ log.info("json:{}", jsonObject);
+ Object trade_state = jsonObject.get("trade_state");
+ if (trade_state != null) {
+ String tradeState = trade_state.toString();
+ if ("SUCCESS".equals(tradeState)) {
+ return PayOrderStatus.SUCCESS;
+ } else if ("USERPAYING".equals(tradeState)) {
+ return PayOrderStatus.USERPAYING;
+ } else {
+ return PayOrderStatus.FAILED;
+ }
+ }
+ return PayOrderStatus.UNKNOWN;
+ }
+
+ /**
+ * 服务商查询订单
+ *
+ * @param orderNo
+ * @throws Exception
+ */
+ public static PayOrderStatus queryOrder(String orderNo) throws IOException, URISyntaxException {
+ URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/id/" + orderNo + "?sp_mchid=" + SPMECHID + "&sub_mchid=" + SUBMCHID);
+ return getPayOrderStatus(uriBuilder);
+ }
+
+ /**
+ * 商户订单号查询
+ *
+ * @param transactionId 微信订单号
+ * @return
+ * @throws IOException
+ * @throws URISyntaxException
+ */
+ public static PayOrderStatus wechatOrder(String transactionId) throws IOException, URISyntaxException {
+ URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/out-trade-no/" + transactionId + "?sp_mchid=" + SPMECHID + "&sub_mchid=" + SUBMCHID);
+ return getPayOrderStatus(uriBuilder);
+ }
+
+
+ /**
+ * 服务商关闭订单
+ *
+ * @param orderNo 商户订单号
+ */
+ public static void closeOrder(String orderNo) throws IOException {
+ HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/out-trade-no/" + orderNo + "/close");
+ httpPost.addHeader("Accept", "application/json");
+ httpPost.addHeader("Content-type", "application/json; charset=utf-8");
+
+ JSONObject params = new JSONObject();
+ params.put("sp_mchid", SPMECHID);
+ params.put("sub_mchid", SUBMCHID);
+
+ httpPost.setEntity(new StringEntity(params.toJSONString(), "UTF-8"));
+ getWechatPayHttpClient().execute(httpPost);
+ //接口响应204,无内容
+ }
+
+
+ /**
+ * 服务商退款
+ *
+ * @param refund 退款金额
+ * @param outTradeNo 商户订单号
+ * @param outRefundNo 商户退款单号
+ * @param notifyUrl 退款回调url
+ * @param total 原订单金额
+ * @return
+ * @throws Exception
+ */
+ public static String refunds(int refund, String outTradeNo, String outRefundNo, String notifyUrl, int total) throws Exception {
+ HttpPost httpPost = new HttpPost(URL_REFUND_PAY);
+ httpPost.addHeader("Accept", "application/json");
+ httpPost.addHeader("Content-type", "application/json; charset=utf-8");
+
+ JSONObject params = new JSONObject();
+ JSONObject amount = new JSONObject();
+
+ //金额信息
+ amount.put("refund", refund);
+ //原订单金额
+ amount.put("total", total);
+ //退款币种
+ amount.put("currency", "CNY");
+ //子商户号 否
+ params.put("sub_mchid", SUBMCHID);
+//// 微信支付订单号 (二选一)
+// params.put("transaction_id", SUBMCHID);
+ //商户订单号 (二选一)
+ params.put("out_trade_no", outTradeNo);
+ //商户退款单号
+ log.info("商户退款单号----------------------------------------out_trade_no:{}", outRefundNo);
+ params.put("out_refund_no", outRefundNo);
+ //退款结果回调url 否
+ params.put("notify_url", notifyUrl);
+ //金额信息
+ params.put("amount", amount);
+
+ httpPost.setEntity(new StringEntity(params.toJSONString(), "UTF-8"));
+ CloseableHttpResponse response = (CloseableHttpResponse) getWechatPayHttpClient().execute(httpPost);
+ String bodyAsString = EntityUtils.toString(response.getEntity());
+ JSONObject respJson = JSONObject.parseObject(bodyAsString);
+
+ log.info("respJson:{}", respJson);
+ Object result = respJson.get("status");
+ String status = result.toString();
+ if ("SUCCESS".equals(status) || "PROCESSING".equals(status)) {
+ return status;
+ } else {
+ throw new PayException("[" + respJson.get("err_code") + "]"
+ + respJson.get("err_code_des"));
+ }
+ }
+
+ /**
+ * 查询单笔退款
+ */
+ public static JSONObject selRechargeResult(String out_refund_no) throws Exception {
+ HttpGet httpGet = new HttpGet(SEL_URL_REFUND_PAY + "/" + out_refund_no + "?sub_mchid=" + SUBMCHID);
+ httpGet.addHeader("Accept", "application/json");
+ httpGet.addHeader("Content-type", "application/json; charset=utf-8");
+ httpGet.addHeader("Wechatpay-Serial", getVerifier().getValidCertificate().getSerialNumber().toString(16));
+
+ CloseableHttpResponse response = (CloseableHttpResponse) getWechatPayHttpClient().execute(httpGet);
+ String bodyAsString = EntityUtils.toString(response.getEntity());
+ return JSONObject.parseObject(bodyAsString);
+ }
+
+ /**
+ * 微信退款结果通知
+ */
+ public static JSONObject tuiKuanResult(HttpServletRequest request) throws Exception {
+ //一、验证签名
+ //1.1获取平台证书
+ getVerifier();
+ //1.2检查平台证书序列号
+ String wepaySerial = request.getHeader("Wechatpay-Serial");
+ if (wepaySerial == null) {
+ throw new PayException(-9, "平台证书序列号为空");
+ }
+ //获取平台证书序列号
+ BigInteger currentSerial = getVerifier().getValidCertificate().getSerialNumber();
+ if (StrUtil.isEmpty(wepaySerial) || !wepaySerial.equalsIgnoreCase(currentSerial.toString(16))) {
+ throw new PayException(-9, "证书序列号不一致");
+ }
+ String wepayNonce = request.getHeader("Wechatpay-Nonce");
+ String wepayTimestamp = request.getHeader("Wechatpay-Timestamp");
+ String wepayBody = null;
+ BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(),StandardCharsets.UTF_8));
+ String line = null;
+ StringBuilder body = new StringBuilder();
+ while ((line = br.readLine()) != null) {
+ body.append(line);
+ }
+ if (StrUtil.isEmpty(body.toString())) {
+ throw new PayException(-9, "body is null");
+ }
+ wepayBody = body.toString();
+
+ String message = wepayTimestamp + "\n"
+ + wepayNonce + "\n"
+ + body.toString() + "\n";
+ //1.4获取应答签名
+ String wepySignature = request.getHeader("Wechatpay-Signature");
+
+ //1.5验证签名
+ boolean rr = getVerifier().verify(wepaySerial,
+ message.getBytes(StandardCharsets.UTF_8),wepySignature);
+ if (!rr){
+ }
+ JSONObject jsonObject = JSONObject.parseObject(wepayBody);
+ JSONObject resource = (JSONObject) jsonObject.get("resource");
+ AesUtil aesUtil = new AesUtil(API_V3_Key.getBytes("utf-8"));
+ //解密
+ String decryptToString = aesUtil.decryptToString(
+ resource.get("associated_data").toString().getBytes(),//附加数据
+ resource.get("nonce").toString().getBytes(),//随机串
+ resource.get("ciphertext").toString());//数据密文
+ JSONObject parseObject = JSONObject.parseObject(decryptToString);
+ return parseObject;
+ }
+
+
+ /**
+ * 企业付款到零钱
+ *
+ * @param partner_trade_no 商户订单号
+ * @param openid 用户openid
+ * @param total_fee 金额
+ * @param desc 付款备注
+ * @param spbill_create_ip Ip地址
+ * @return
+ * @throws Exception
+ */
+ public static Map payToUsrWx(
+ String partner_trade_no, String openid, int total_fee, String desc, String spbill_create_ip)
+ throws Exception {
+ //1.构造请求字符串
+ Map reqMap = new HashMap();
+ reqMap.put("mch_appid", SUBAPPID);
+ reqMap.put("mchid", SUBMCHID);
+ //reqMap.put("device_info",null); //不能添加空字段,Jackson会生成闭包xml 导致签名失败
+ reqMap.put("nonce_str", createNonceStr());
+ reqMap.put("partner_trade_no", partner_trade_no);
+ reqMap.put("openid", openid);
+ reqMap.put("check_name", "NO_CHECK");
+ //reqMap.put("re_user_name",null);
+ reqMap.put("amount", total_fee + "");
+ reqMap.put("desc", desc);
+ reqMap.put("spbill_create_ip", spbill_create_ip);
+ reqMap.put("sign", createSign(reqMap));
+
+ //2.发送付款请求
+ String reqrXml = JacksonUtil.mapToXml(paraFilterEmpty(reqMap), "xml");
+ String respXml = HttpsUtil.httpsRequest(URL_PAY_TO_USR_WX, "POST", reqrXml,
+ PATH_WX_CRET, SUBMCHID);
+ System.out.println("---------------PayToUsrWx Request Xml-----------------");
+ System.out.println(reqrXml);
+ System.out.println("---------------PayToUsrWx Response Xml-----------------");
+ System.out.println(respXml);
+ System.out.println("---------------PayToUsrWx end-----------------");
+
+ //3.判断成功失败
+ Map respMap = JacksonUtil.xmlToMap(new ByteArrayInputStream(respXml.getBytes(StandardCharsets.UTF_8)));
+ String return_code, result_code;
+ return_code = String.valueOf(respMap.get("return_code"));
+ result_code = String.valueOf(respMap.get("result_code"));
+
+ if (!StrUtil.isEmpty(return_code) && !StrUtil.isEmpty(result_code)) {
+ if (return_code.equals("SUCCESS") && return_code.equals(result_code)) {
+ return respMap;
+ } else {
+ throw new PayException("[" + respMap.get("err_code") + "]"
+ + respMap.get("err_code_des"));
+ }
+ } else {
+ throw new PayException(String.valueOf(respMap.get("return_msg")));
+ }
+ //return null;
+ }
+
+ /**
+ * Create Sign
+ *
+ * @param sParaTemp
+ * @return
+ */
+ private static String createSign(Map sParaTemp) throws FileNotFoundException {
+ // 除去数组中的空值和签名参数
+ Map sPara = paraFilter(sParaTemp);
+ String prestr = createLinkString(sPara); // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
+ //MD5运算生成签名
+ String sign = sign(prestr, getPrivateKey().toString(), "utf-8").toUpperCase();
+// return sign;
+ return sign;
+ }
+
+ /**
+ * 签名字符串
+ *
+ * @param text 需要签名的字符串
+ * @param key 密钥
+ * @param input_charset 编码格式
+ * @return 签名结果
+ */
+ private static String sign(String text, String key, String input_charset) {
+ text = text + "&key=" + key;
+ return DigestUtils.md5Hex(getContentBytes(text, input_charset));
+ }
+
+ /**
+ * @param content
+ * @param charset
+ * @return
+ * @throws
+ * @throws UnsupportedEncodingException
+ */
+ private static byte[] getContentBytes(String content, String charset) {
+ if (charset == null || "".equals(charset)) {
+ return content.getBytes();
+ }
+ try {
+ return content.getBytes(charset);
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
+ }
+ }
+
+ /**
+ * 除去数组中的空值和签名参数
+ *
+ * @param sArray 签名参数组
+ * @return 去掉空值与签名参数后的新签名参数组
+ */
+ private static Map paraFilter(Map sArray) {
+ Map result = new HashMap();
+ if (sArray == null || sArray.size() <= 0) {
+ return result;
+ }
+ for (String key : sArray.keySet()) {
+ Object objVal = sArray.get(key);
+ if (objVal == null) {
+ continue;
+ }
+ String value = String.valueOf(objVal);
+ if (StrUtil.isEmpty(value) || key.equalsIgnoreCase("sign") || key.equalsIgnoreCase("sign_type")) {
+ continue;
+ }
+ result.put(key, value);
+ }
+ return result;
+ }
+
+ /**
+ * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
+ *
+ * @param params 需要排序并参与字符拼接的参数组
+ * @return 拼接后字符串
+ */
+ private static String createLinkString(Map params) {
+ List keys = new ArrayList(params.keySet());
+ Collections.sort(keys);
+ String prestr = "";
+ for (int i = 0; i < keys.size(); i++) {
+ String key = keys.get(i);
+ String value = params.get(key);
+ if (i == keys.size() - 1) {// 拼接时,不包括最后一个&字符
+ prestr = prestr + key + "=" + value;
+ } else {
+ prestr = prestr + key + "=" + value + "&";
+ }
+ }
+ return prestr;
+ }
+
+
+ /**
+ * 除去数组中的空值和签名参数
+ *
+ * @param sArray 签名参数组
+ * @return 去掉空值与签名参数后的新签名参数组
+ */
+ private static Map paraFilterEmpty(Map sArray) {
+ Map result = new HashMap();
+ if (sArray == null || sArray.size() <= 0) {
+ return result;
+ }
+ for (String key : sArray.keySet()) {
+ Object objVal = sArray.get(key);
+ if (objVal == null) {
+ continue;
+ }
+ String value = String.valueOf(objVal);
+ result.put(key, value);
+ }
+ return result;
+ }
}
\ No newline at end of file
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/payutil/WxTokenUtil.java b/util_wechat/src/main/java/com/ccsens/wechatutil/payutil/WxTokenUtil.java
similarity index 97%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/payutil/WxTokenUtil.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/payutil/WxTokenUtil.java
index bd77ea6..fe1e470 100644
--- a/wechatutil/src/main/java/com/ccsens/wechatutil/payutil/WxTokenUtil.java
+++ b/util_wechat/src/main/java/com/ccsens/wechatutil/payutil/WxTokenUtil.java
@@ -1,64 +1,64 @@
-package com.ccsens.wechatutil.payutil;
-
-import com.alibaba.fastjson.JSONObject;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.util.EntityUtils;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-/**
- * @author :mr.zhangsan
- * @date :Created in 2021/4/15 21:11
- * @version v1.0:
- */
-
-public class WxTokenUtil {
-
- //测试APPID
- private static final String appid = "wxf30402e727f0840a";
- //测试secret
- private static final String secret = "70402290ac83857c7324b0ee881b544a";
- // 测试商户号
- private static final String SUBMCHID = "1611259929";
-
- /**
- * 获取小程序全局唯一后台接口调用凭据(access_token)
- */
- private static final String URL_GETTOKEN_PAY
- = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
-
- public static String getToken() throws Exception{
-
- HttpGet httpGet = new HttpGet(URL_GETTOKEN_PAY);
- httpGet.addHeader("Accept", "application/json");
- httpGet.addHeader("Content-type", "application/json; charset=utf-8");
- try {
- httpGet.addHeader("Wechatpay-Serial", WxPayProviderUtils.getVerifier().getValidCertificate().getSerialNumber().toString(16));
- }catch (FileNotFoundException e) {
- e.printStackTrace();
- throw new FileNotFoundException("获取微信平台证书失败");
- }
- String bodyAsString = "";
- try {
- CloseableHttpResponse response = (CloseableHttpResponse) WxPayProviderUtils.getWechatPayHttpClient().execute(httpGet);
- try {
- bodyAsString = EntityUtils.toString(response.getEntity());
- }catch (IOException e) {
- e.printStackTrace();
- throw new FileNotFoundException("bodyAsString转换错误");
- }
- }catch (IOException e) {
- e.printStackTrace();
- throw new FileNotFoundException("根据微信平台证书获取httpclient失败");
- }
- JSONObject respJson = JSONObject.parseObject(bodyAsString);
- Object access_token = respJson.get("access_token");
- if (access_token != null) {
- return access_token.toString();
- }else {
- throw new Exception("获取WxToken失败");
- }
- }
-}
+package com.ccsens.wechatutil.payutil;
+
+import com.alibaba.fastjson.JSONObject;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.util.EntityUtils;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * @author :mr.zhangsan
+ * @date :Created in 2021/4/15 21:11
+ * @version v1.0:
+ */
+
+public class WxTokenUtil {
+
+ //测试APPID
+ private static final String appid = "wxf30402e727f0840a";
+ //测试secret
+ private static final String secret = "70402290ac83857c7324b0ee881b544a";
+ // 测试商户号
+ private static final String SUBMCHID = "1611259929";
+
+ /**
+ * 获取小程序全局唯一后台接口调用凭据(access_token)
+ */
+ private static final String URL_GETTOKEN_PAY
+ = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
+
+ public static String getToken() throws Exception{
+
+ HttpGet httpGet = new HttpGet(URL_GETTOKEN_PAY);
+ httpGet.addHeader("Accept", "application/json");
+ httpGet.addHeader("Content-type", "application/json; charset=utf-8");
+ try {
+ httpGet.addHeader("Wechatpay-Serial", WxPayProviderUtils.getVerifier().getValidCertificate().getSerialNumber().toString(16));
+ }catch (FileNotFoundException e) {
+ e.printStackTrace();
+ throw new FileNotFoundException("获取微信平台证书失败");
+ }
+ String bodyAsString = "";
+ try {
+ CloseableHttpResponse response = (CloseableHttpResponse) WxPayProviderUtils.getWechatPayHttpClient().execute(httpGet);
+ try {
+ bodyAsString = EntityUtils.toString(response.getEntity());
+ }catch (IOException e) {
+ e.printStackTrace();
+ throw new FileNotFoundException("bodyAsString转换错误");
+ }
+ }catch (IOException e) {
+ e.printStackTrace();
+ throw new FileNotFoundException("根据微信平台证书获取httpclient失败");
+ }
+ JSONObject respJson = JSONObject.parseObject(bodyAsString);
+ Object access_token = respJson.get("access_token");
+ if (access_token != null) {
+ return access_token.toString();
+ }else {
+ throw new Exception("获取WxToken失败");
+ }
+ }
+}
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/util/TC3Util.java b/util_wechat/src/main/java/com/ccsens/wechatutil/util/TC3Util.java
similarity index 100%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/util/TC3Util.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/util/TC3Util.java
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/util/WeiXinPropUtil.java b/util_wechat/src/main/java/com/ccsens/wechatutil/util/WeiXinPropUtil.java
similarity index 100%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/util/WeiXinPropUtil.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/util/WeiXinPropUtil.java
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/util/WxCodeError.java b/util_wechat/src/main/java/com/ccsens/wechatutil/util/WxCodeError.java
similarity index 96%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/util/WxCodeError.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/util/WxCodeError.java
index 0f2a505..f19b4e8 100644
--- a/wechatutil/src/main/java/com/ccsens/wechatutil/util/WxCodeError.java
+++ b/util_wechat/src/main/java/com/ccsens/wechatutil/util/WxCodeError.java
@@ -1,15 +1,15 @@
-package com.ccsens.wechatutil.util;
-
-import com.ccsens.util.CodeError;
-
-/**
- * @author 逗
- */
-public class WxCodeError extends CodeError {
-
- public static final Code WX_HTTP_ERROR = new Code(1,"微信接口请求失败", true);
- public static final Code ACCESS_TOKEN_ERROR = new Code(2,"accessToken获取失败", true);
- public static final Code OPENID_ERROR = new Code(2,"openId获取失败", true);
-
-
-}
+package com.ccsens.wechatutil.util;
+
+import com.ccsens.util.CodeError;
+
+/**
+ * @author 逗
+ */
+public class WxCodeError extends CodeError {
+
+ public static final Code WX_HTTP_ERROR = new Code(1,"微信接口请求失败", true);
+ public static final Code ACCESS_TOKEN_ERROR = new Code(2,"accessToken获取失败", true);
+ public static final Code OPENID_ERROR = new Code(2,"openId获取失败", true);
+
+
+}
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/util/WxConstant.java b/util_wechat/src/main/java/com/ccsens/wechatutil/util/WxConstant.java
similarity index 97%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/util/WxConstant.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/util/WxConstant.java
index 8111685..009686c 100644
--- a/wechatutil/src/main/java/com/ccsens/wechatutil/util/WxConstant.java
+++ b/util_wechat/src/main/java/com/ccsens/wechatutil/util/WxConstant.java
@@ -1,129 +1,129 @@
-package com.ccsens.wechatutil.util;
-
-import cn.hutool.core.util.StrUtil;
-import com.ccsens.util.JacksonUtil;
-import com.ccsens.util.exception.BaseException;
-import com.ccsens.wechatutil.bean.po.WxBaseEntity;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author 逗
- */
-public class WxConstant {
-
- /*** 默认小程序 */
- public static final String ANYRING = "anyring";
-
-
- /*** 公众号获取accessToken */
- public static final String URL_GET_OAUTH2_ACCESS_TOKEN = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%1$s&secret=%2$s&code=%3$s&grant_type=authorization_code";
- /*** 公众号发送订阅消息 */
- public static final String MESSAGE_TEMPLATE_SEND = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%1$s";
- /** 创建二维码 */
- public static final String QR_CODE_CREATE = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={}";
- /**根据openId获取用户信息*/
- public static final String USER_INFO = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%1$s&openid=%2$s&lang=zh_CN";
-
-
- /*** 小程序登录路径 */
- public static final String MINI_PROGRAM_LOGIN = "https://api.weixin.qq.com/sns/jscode2session?appid=%1$s&secret=%2$s&js_code=%3$s&grant_type=%4$s";
- /*** 通过网页授权和openId获取用户信息 */
- public static final String URL_GET_OAUTH2_USER_INFO = "https://api.weixin.qq.com/sns/userinfo?access_token=%1$s&openid=%2$s";
- /*** 获取小程序码A */
- public static final String URL_GET_WX_CODE_A = "https://api.weixin.qq.com/wxa/getwxacode?access_token=%1$s";
- /*** 获取小程序码B */
- public static final String URL_GET_WX_CODE_B = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%1$s";
- /*** 获取小程序码C */
- public static final String URL_GET_WX_CODE_C = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=%1$s";
- /*** 小程序获取accessToken */
- public static final String URL_GET_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%1$s&secret=%2$s";
- /*** 小程序发送订阅消息 */
- public static final String URL_SEND_SUBSCRIBE_MESSAGE = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=%1$s";
- /*** 小程序消息模板--支付 */
- public static String SUBSCRIBE_MSG_ID_BUY = "bqdx4FW51G-JLU6HjL6LyvUbjpo4rFK6CPor2-w3VwM";
- /*** 小程序消息模板--订单发送 */
- public static String SUBSCRIBE_MSG_ID_ORDERSEND = "5-rhM8h3x1W82tHCt18g9iXyGELyUKQtBDZiFjgItOo";
- /*** 小程序登录路径内的type */
- public static final String GRANT_TYPE = "authorization_code";
-
- /*** redis内存储AccessToken的Key */
- public static final String ACCESS_TOKEN = "tall_wx_access_token_";
-
- /*** 机器人消息类型--文本 */
- public static final String TEXT = "text";
- /*** 机器人消息类型--markdown */
- public static final String MARKDOWN = "markdown";
-
-
- /**
- * 小程序订阅消息类型
- */
- public enum Packet_Notify_Type {
- /**
- * 消息类型
- */
- Buy(1, "购买"),
- ReceiveSubscriBuyData(2, "订单发货");
-
- public int value;
- public String phase;
-
- Packet_Notify_Type(int value, String thePhase) {
- this.value = value;
- this.phase = thePhase;
- }
- }
-
- /*** 小程序appId */
- public static final Map APP_ID = new HashMap<>();
- static {
- //默认小程序
- APP_ID.put("anyring", "wx356e01c7eb01d55d");
- //tall3小程序
- APP_ID.put("tall", "wxf72a76c2ea24a472");
- //赛跑小程序
- APP_ID.put("SP", "wx2ebb5cf926fe1ddb");
- //数钱小程序
- APP_ID.put("SQ", "wx55fa235267ca11e6");
- //拔河小程序
- APP_ID.put("BH", "wxd06d18fe7c75b498");
- //健康码小程序
- APP_ID.put("health", "wx2f9ef33e08053bbf");
- //企业微信
- APP_ID.put("enterprise", "wx808fa75921bd8f22");
- }
-
- /*** 小程序secret */
- public static final Map SECRET = new HashMap<>();
- static {
- //默认小程序
- SECRET.put("anyring", "353033db85d4b5a35f05d1c0176a0cc6");
- //tall3小程序
- SECRET.put("tall", "5aa3fc421a149ec1e59a4a4f472e1223");
- //赛跑小程序
- SECRET.put("SP", "38e4425b8e3647015b439c6d38172b49");
- //数钱小程序
- SECRET.put("SQ", "d75a5a7538ff9c72f781738850817081");
- //拔河小程序
- SECRET.put("BH", "202ad7f3d95b0532948c667c468c9a56");
- //健康码小程序
- SECRET.put("health", "af90801c26bc177681b2c39a603605b9");
- //企业微信
- SECRET.put("enterprise", "8d2e95462bfeab363ee84776bc807859");
- }
-
-
- public static void pageResult(String result) {
- try {
- if (StrUtil.isEmpty(result) || null == JacksonUtil.jsonToBean(result, WxBaseEntity.class)) {
- throw new BaseException(WxCodeError.WX_HTTP_ERROR);
- }
- } catch (IOException e) {
- throw new BaseException(e.getMessage());
- }
- }
-
-}
+package com.ccsens.wechatutil.util;
+
+import cn.hutool.core.util.StrUtil;
+import com.ccsens.util.JacksonUtil;
+import com.ccsens.util.exception.BaseException;
+import com.ccsens.wechatutil.bean.po.WxBaseEntity;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author 逗
+ */
+public class WxConstant {
+
+ /*** 默认小程序 */
+ public static final String ANYRING = "anyring";
+
+
+ /*** 公众号获取accessToken */
+ public static final String URL_GET_OAUTH2_ACCESS_TOKEN = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%1$s&secret=%2$s&code=%3$s&grant_type=authorization_code";
+ /*** 公众号发送订阅消息 */
+ public static final String MESSAGE_TEMPLATE_SEND = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%1$s";
+ /** 创建二维码 */
+ public static final String QR_CODE_CREATE = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={}";
+ /**根据openId获取用户信息*/
+ public static final String USER_INFO = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%1$s&openid=%2$s&lang=zh_CN";
+
+
+ /*** 小程序登录路径 */
+ public static final String MINI_PROGRAM_LOGIN = "https://api.weixin.qq.com/sns/jscode2session?appid=%1$s&secret=%2$s&js_code=%3$s&grant_type=%4$s";
+ /*** 通过网页授权和openId获取用户信息 */
+ public static final String URL_GET_OAUTH2_USER_INFO = "https://api.weixin.qq.com/sns/userinfo?access_token=%1$s&openid=%2$s";
+ /*** 获取小程序码A */
+ public static final String URL_GET_WX_CODE_A = "https://api.weixin.qq.com/wxa/getwxacode?access_token=%1$s";
+ /*** 获取小程序码B */
+ public static final String URL_GET_WX_CODE_B = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%1$s";
+ /*** 获取小程序码C */
+ public static final String URL_GET_WX_CODE_C = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=%1$s";
+ /*** 小程序获取accessToken */
+ public static final String URL_GET_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%1$s&secret=%2$s";
+ /*** 小程序发送订阅消息 */
+ public static final String URL_SEND_SUBSCRIBE_MESSAGE = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=%1$s";
+ /*** 小程序消息模板--支付 */
+ public static String SUBSCRIBE_MSG_ID_BUY = "bqdx4FW51G-JLU6HjL6LyvUbjpo4rFK6CPor2-w3VwM";
+ /*** 小程序消息模板--订单发送 */
+ public static String SUBSCRIBE_MSG_ID_ORDERSEND = "5-rhM8h3x1W82tHCt18g9iXyGELyUKQtBDZiFjgItOo";
+ /*** 小程序登录路径内的type */
+ public static final String GRANT_TYPE = "authorization_code";
+
+ /*** redis内存储AccessToken的Key */
+ public static final String ACCESS_TOKEN = "tall_wx_access_token_";
+
+ /*** 机器人消息类型--文本 */
+ public static final String TEXT = "text";
+ /*** 机器人消息类型--markdown */
+ public static final String MARKDOWN = "markdown";
+
+
+ /**
+ * 小程序订阅消息类型
+ */
+ public enum Packet_Notify_Type {
+ /**
+ * 消息类型
+ */
+ Buy(1, "购买"),
+ ReceiveSubscriBuyData(2, "订单发货");
+
+ public int value;
+ public String phase;
+
+ Packet_Notify_Type(int value, String thePhase) {
+ this.value = value;
+ this.phase = thePhase;
+ }
+ }
+
+ /*** 小程序appId */
+ public static final Map APP_ID = new HashMap<>();
+ static {
+ //默认小程序
+ APP_ID.put("anyring", "wx356e01c7eb01d55d");
+ //tall3小程序
+ APP_ID.put("tall", "wxf72a76c2ea24a472");
+ //赛跑小程序
+ APP_ID.put("SP", "wx2ebb5cf926fe1ddb");
+ //数钱小程序
+ APP_ID.put("SQ", "wx55fa235267ca11e6");
+ //拔河小程序
+ APP_ID.put("BH", "wxd06d18fe7c75b498");
+ //健康码小程序
+ APP_ID.put("health", "wx2f9ef33e08053bbf");
+ //企业微信
+ APP_ID.put("enterprise", "wx808fa75921bd8f22");
+ }
+
+ /*** 小程序secret */
+ public static final Map SECRET = new HashMap<>();
+ static {
+ //默认小程序
+ SECRET.put("anyring", "353033db85d4b5a35f05d1c0176a0cc6");
+ //tall3小程序
+ SECRET.put("tall", "5aa3fc421a149ec1e59a4a4f472e1223");
+ //赛跑小程序
+ SECRET.put("SP", "38e4425b8e3647015b439c6d38172b49");
+ //数钱小程序
+ SECRET.put("SQ", "d75a5a7538ff9c72f781738850817081");
+ //拔河小程序
+ SECRET.put("BH", "202ad7f3d95b0532948c667c468c9a56");
+ //健康码小程序
+ SECRET.put("health", "af90801c26bc177681b2c39a603605b9");
+ //企业微信
+ SECRET.put("enterprise", "8d2e95462bfeab363ee84776bc807859");
+ }
+
+
+ public static void pageResult(String result) {
+ try {
+ if (StrUtil.isEmpty(result) || null == JacksonUtil.jsonToBean(result, WxBaseEntity.class)) {
+ throw new BaseException(WxCodeError.WX_HTTP_ERROR);
+ }
+ } catch (IOException e) {
+ throw new BaseException(e.getMessage());
+ }
+ }
+
+}
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/wxcommon/WxCommonUtil.java b/util_wechat/src/main/java/com/ccsens/wechatutil/wxcommon/WxCommonUtil.java
similarity index 97%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/wxcommon/WxCommonUtil.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/wxcommon/WxCommonUtil.java
index 897f7df..07652d5 100644
--- a/wechatutil/src/main/java/com/ccsens/wechatutil/wxcommon/WxCommonUtil.java
+++ b/util_wechat/src/main/java/com/ccsens/wechatutil/wxcommon/WxCommonUtil.java
@@ -1,68 +1,68 @@
-package com.ccsens.wechatutil.wxcommon;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.http.HttpRequest;
-import com.ccsens.util.JacksonUtil;
-import com.ccsens.util.RedisUtil;
-import com.ccsens.util.WebConstant;
-import com.ccsens.util.bean.wx.po.WxAccessToken;
-import com.ccsens.util.exception.BaseException;
-import com.ccsens.wechatutil.util.WxCodeError;
-import com.ccsens.wechatutil.util.WxConstant;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.Resource;
-import java.io.IOException;
-/**
- * @author 逗
- */
-@Slf4j
-@Component
-public class WxCommonUtil {
-
- @Resource
- private RedisUtil redisUtil;
- private static WxCommonUtil util;
-
- @PostConstruct
- public void init(){
- util = this;
- }
-
-
-
- /**
- * 小程序获取Access_token
- */
- public static String getAccessToken(String appId, String secret) throws BaseException {
- log.info("获取accessToken,appid:{}", appId.substring(appId.length() - 4));
- Object obj = util.redisUtil.get(WxConstant.ACCESS_TOKEN + appId);
- if (obj == null || StrUtil.isBlank((String) obj)) {
- WxAccessToken wxAccessToken;
- String url = String.format(WxConstant.URL_GET_ACCESS_TOKEN, appId, secret);
- String response = HttpRequest.get(url).execute().body();
- log.info("getAccessToken: {}", response);
- try {
- if (StrUtil.isEmpty(response) || null == (wxAccessToken = JacksonUtil.jsonToBean(response, WxAccessToken.class))) {
- throw new BaseException(WxCodeError.WX_HTTP_ERROR);
- }
- } catch (IOException e) {
- throw new BaseException(e.getMessage());
- }
-
- if (null != wxAccessToken.getErrcode()) {
- throw new BaseException(wxAccessToken.getErrcode(), wxAccessToken.getErrmsg());
- }
- if (StrUtil.isEmpty(wxAccessToken.getAccessToken())) {
- throw new BaseException(WxCodeError.ACCESS_TOKEN_ERROR);
- }
- util.redisUtil.set(WebConstant.Wx.ACCESS_TOKEN + appId, wxAccessToken.getAccessToken(), WebConstant.Wx.EXPIRE_TIME);
- log.info("存储access_token:{}", wxAccessToken.getAccessToken());
- return wxAccessToken.getAccessToken();
- }
- log.info("读取reids的token:{}", obj);
- return (String) obj;
- }
-}
+package com.ccsens.wechatutil.wxcommon;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpRequest;
+import com.ccsens.util.JacksonUtil;
+import com.ccsens.util.RedisUtil;
+import com.ccsens.util.WebConstant;
+import com.ccsens.util.bean.wx.po.WxAccessToken;
+import com.ccsens.util.exception.BaseException;
+import com.ccsens.wechatutil.util.WxCodeError;
+import com.ccsens.wechatutil.util.WxConstant;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.io.IOException;
+/**
+ * @author 逗
+ */
+@Slf4j
+@Component
+public class WxCommonUtil {
+
+ @Resource
+ private RedisUtil redisUtil;
+ private static WxCommonUtil util;
+
+ @PostConstruct
+ public void init(){
+ util = this;
+ }
+
+
+
+ /**
+ * 小程序获取Access_token
+ */
+ public static String getAccessToken(String appId, String secret) throws BaseException {
+ log.info("获取accessToken,appid:{}", appId.substring(appId.length() - 4));
+ Object obj = util.redisUtil.get(WxConstant.ACCESS_TOKEN + appId);
+ if (obj == null || StrUtil.isBlank((String) obj)) {
+ WxAccessToken wxAccessToken;
+ String url = String.format(WxConstant.URL_GET_ACCESS_TOKEN, appId, secret);
+ String response = HttpRequest.get(url).execute().body();
+ log.info("getAccessToken: {}", response);
+ try {
+ if (StrUtil.isEmpty(response) || null == (wxAccessToken = JacksonUtil.jsonToBean(response, WxAccessToken.class))) {
+ throw new BaseException(WxCodeError.WX_HTTP_ERROR);
+ }
+ } catch (IOException e) {
+ throw new BaseException(e.getMessage());
+ }
+
+ if (null != wxAccessToken.getErrcode()) {
+ throw new BaseException(wxAccessToken.getErrcode(), wxAccessToken.getErrmsg());
+ }
+ if (StrUtil.isEmpty(wxAccessToken.getAccessToken())) {
+ throw new BaseException(WxCodeError.ACCESS_TOKEN_ERROR);
+ }
+ util.redisUtil.set(WebConstant.Wx.ACCESS_TOKEN + appId, wxAccessToken.getAccessToken(), WebConstant.Wx.EXPIRE_TIME);
+ log.info("存储access_token:{}", wxAccessToken.getAccessToken());
+ return wxAccessToken.getAccessToken();
+ }
+ log.info("读取reids的token:{}", obj);
+ return (String) obj;
+ }
+}
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/wxenterprise/EnterpriseRobotUtil.java b/util_wechat/src/main/java/com/ccsens/wechatutil/wxenterprise/EnterpriseRobotUtil.java
similarity index 97%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/wxenterprise/EnterpriseRobotUtil.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/wxenterprise/EnterpriseRobotUtil.java
index c06d0ef..e066a7c 100644
--- a/wechatutil/src/main/java/com/ccsens/wechatutil/wxenterprise/EnterpriseRobotUtil.java
+++ b/util_wechat/src/main/java/com/ccsens/wechatutil/wxenterprise/EnterpriseRobotUtil.java
@@ -1,83 +1,83 @@
-package com.ccsens.wechatutil.wxenterprise;
-
-import cn.hutool.core.collection.CollectionUtil;
-import com.ccsens.util.JacksonUtil;
-import com.ccsens.wechatutil.bean.dto.WxMessageDto;
-import com.ccsens.wechatutil.util.WxConstant;
-import lombok.extern.slf4j.Slf4j;
-
-import java.io.*;
-import java.net.URL;
-import java.net.URLConnection;
-import java.nio.charset.StandardCharsets;
-
-/**
- * @author 逗
- */
-@Slf4j
-public class EnterpriseRobotUtil {
- /**
- * 微信机器人
- * @param robotMessage 机器人消息
- * @throws Exception 异常
- */
- public static void sendRobotInfo(WxMessageDto.RobotMessage robotMessage)throws Exception {
- WxMessageDto.WxRobotVo wxRobotVo = new WxMessageDto.WxRobotVo();
- wxRobotVo.setMsgtype(robotMessage.getMsgType());
- if(WxConstant.TEXT.equalsIgnoreCase(robotMessage.getMsgType())){
- WxMessageDto.WxRobotText wxRobotText = new WxMessageDto.WxRobotText();
- wxRobotText.setContent(robotMessage.getContent());
- if(CollectionUtil.isNotEmpty(robotMessage.getMentionedList())){
- wxRobotText.setMentioned_list(robotMessage.getMentionedList());
- }
- if(CollectionUtil.isNotEmpty(robotMessage.getMentionedMobileList())){
- wxRobotText.setMentioned_mobile_list(robotMessage.getMentionedMobileList());
- }
- wxRobotVo.setText(wxRobotText);
- }else if(WxConstant.MARKDOWN.equalsIgnoreCase(robotMessage.getMsgType())){
- WxMessageDto.WxRobotMarkdown wxRobotMarkdown = new WxMessageDto.WxRobotMarkdown();
- wxRobotMarkdown.setContent(robotMessage.getContent());
- wxRobotVo.setMarkdown(wxRobotMarkdown);
- }
-
- String body = JacksonUtil.beanToJson(wxRobotVo);
- log.info(body);
- sendPost(robotMessage.getWebHook(),body);
- }
-
-
- public static void sendPost(String url, String param){
- PrintWriter out = null;
- BufferedReader in = null;
- try {
- URL realUrl = new URL(url);
- // 打开和URL之间的连接
- URLConnection conn = realUrl.openConnection();
- // 发送POST请求必须设置如下两行
- conn.setDoOutput(true);
- conn.setDoInput(true);
- // 获取URLConnection对象对应的输出流(设置请求编码为UTF-8)
- out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8));
- // 发送请求参数
- out.print(param);
- // flush输出流的缓冲
- out.flush();
- // 获取请求返回数据(设置返回数据编码为UTF-8)
- in = new BufferedReader(
- new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if (out != null) {
- out.close();
- }
- if (in != null) {
- in.close();
- }
- } catch (IOException ex) {
- ex.printStackTrace();
- }
- }
- }
-}
+package com.ccsens.wechatutil.wxenterprise;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.ccsens.util.JacksonUtil;
+import com.ccsens.wechatutil.bean.dto.WxMessageDto;
+import com.ccsens.wechatutil.util.WxConstant;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @author 逗
+ */
+@Slf4j
+public class EnterpriseRobotUtil {
+ /**
+ * 微信机器人
+ * @param robotMessage 机器人消息
+ * @throws Exception 异常
+ */
+ public static void sendRobotInfo(WxMessageDto.RobotMessage robotMessage)throws Exception {
+ WxMessageDto.WxRobotVo wxRobotVo = new WxMessageDto.WxRobotVo();
+ wxRobotVo.setMsgtype(robotMessage.getMsgType());
+ if(WxConstant.TEXT.equalsIgnoreCase(robotMessage.getMsgType())){
+ WxMessageDto.WxRobotText wxRobotText = new WxMessageDto.WxRobotText();
+ wxRobotText.setContent(robotMessage.getContent());
+ if(CollectionUtil.isNotEmpty(robotMessage.getMentionedList())){
+ wxRobotText.setMentioned_list(robotMessage.getMentionedList());
+ }
+ if(CollectionUtil.isNotEmpty(robotMessage.getMentionedMobileList())){
+ wxRobotText.setMentioned_mobile_list(robotMessage.getMentionedMobileList());
+ }
+ wxRobotVo.setText(wxRobotText);
+ }else if(WxConstant.MARKDOWN.equalsIgnoreCase(robotMessage.getMsgType())){
+ WxMessageDto.WxRobotMarkdown wxRobotMarkdown = new WxMessageDto.WxRobotMarkdown();
+ wxRobotMarkdown.setContent(robotMessage.getContent());
+ wxRobotVo.setMarkdown(wxRobotMarkdown);
+ }
+
+ String body = JacksonUtil.beanToJson(wxRobotVo);
+ log.info(body);
+ sendPost(robotMessage.getWebHook(),body);
+ }
+
+
+ public static void sendPost(String url, String param){
+ PrintWriter out = null;
+ BufferedReader in = null;
+ try {
+ URL realUrl = new URL(url);
+ // 打开和URL之间的连接
+ URLConnection conn = realUrl.openConnection();
+ // 发送POST请求必须设置如下两行
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+ // 获取URLConnection对象对应的输出流(设置请求编码为UTF-8)
+ out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8));
+ // 发送请求参数
+ out.print(param);
+ // flush输出流的缓冲
+ out.flush();
+ // 获取请求返回数据(设置返回数据编码为UTF-8)
+ in = new BufferedReader(
+ new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (out != null) {
+ out.close();
+ }
+ if (in != null) {
+ in.close();
+ }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/wxfiotexplorer/FiotExplorerSigninUtil.java b/util_wechat/src/main/java/com/ccsens/wechatutil/wxfiotexplorer/FiotExplorerSigninUtil.java
similarity index 100%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/wxfiotexplorer/FiotExplorerSigninUtil.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/wxfiotexplorer/FiotExplorerSigninUtil.java
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/wxh5/H5SigninUtil.java b/util_wechat/src/main/java/com/ccsens/wechatutil/wxh5/H5SigninUtil.java
similarity index 97%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/wxh5/H5SigninUtil.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/wxh5/H5SigninUtil.java
index 76b26c2..0032f1a 100644
--- a/wechatutil/src/main/java/com/ccsens/wechatutil/wxh5/H5SigninUtil.java
+++ b/util_wechat/src/main/java/com/ccsens/wechatutil/wxh5/H5SigninUtil.java
@@ -1,105 +1,105 @@
-package com.ccsens.wechatutil.wxh5;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.http.HttpRequest;
-import com.ccsens.util.DateUtil;
-import com.ccsens.util.JacksonUtil;
-import com.ccsens.util.exception.BaseException;
-import com.ccsens.wechatutil.bean.po.WxOauth2AccessToken;
-import com.ccsens.wechatutil.bean.po.WxOauth2UserInfo;
-import com.ccsens.wechatutil.util.WxCodeError;
-import com.ccsens.wechatutil.util.WxConstant;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import java.io.IOException;
-
-/**
- * @author 逗
- */
-@Slf4j
-@Component
-public class H5SigninUtil {
-
- private static String appIdH5;
- private static String secretH5;
-
- @Value("${h5.appId:}")
- public void setAppIdOfficial(String appIdOfficial) {
- H5SigninUtil.appIdH5 = appIdOfficial;
- }
- @Value("${h5.secret:}")
- public void setApplication(String secretOfficial) {
- H5SigninUtil.secretH5 = secretOfficial;
- }
-
- public static WxOauth2UserInfo signinByH5(String code) {
- return signinByH5(code, appIdH5, secretH5);
- }
-
- public static WxOauth2UserInfo signinByH5(String code, String appId, String secret) {
- //获取accessToken
- WxOauth2AccessToken wxOauth2AccessToken = getOauth2AccessToken(code, appId, secret);
- //获取用户信息
- return getOauth2UserInfo(wxOauth2AccessToken.getAccessToken(), wxOauth2AccessToken.getOpenId());
- }
-
- /**
- * 获取网页授权凭证
- * @param code OAuth2授权码
- * @return WxOauth2AccessToken
- */
- private static WxOauth2AccessToken getOauth2AccessToken(String code, String appId, String secret) {
- WxOauth2AccessToken wxOauth2AccessToken;
- //拼接访问路径
- String url = String.format(WxConstant.URL_GET_OAUTH2_ACCESS_TOKEN, appId, secret, code);
- //调用微信接口
- String response = HttpRequest.get(url).execute().body();
- log.info("url: {}\nresponse: {}", url, response);
- try {
- if (StrUtil.isEmpty(response) || null == (wxOauth2AccessToken = JacksonUtil.jsonToBean(response, WxOauth2AccessToken.class))) {
- throw new BaseException(WxCodeError.WX_HTTP_ERROR);
- }
- } catch (IOException e) {
- throw new BaseException(e.getMessage());
- }
- if (null != wxOauth2AccessToken.getErrcode()) {
- throw new BaseException(wxOauth2AccessToken.getErrcode(), wxOauth2AccessToken.getErrmsg());
- }
- if (StrUtil.isEmpty(wxOauth2AccessToken.getAccessToken())) {
- throw new BaseException(WxCodeError.ACCESS_TOKEN_ERROR);
- }
- wxOauth2AccessToken.setCreatedAt(DateUtil.currentSeconds());
- return wxOauth2AccessToken;
- }
-
- /**
- * 通过网页授权accessToken获取用户信息
- * @param accessToken 网页授权接口调用凭证
- * @param openId 用户标识
- * @return SNSUserInfo
- */
- private static WxOauth2UserInfo getOauth2UserInfo(String accessToken, String openId) {
- WxOauth2UserInfo wxOauth2UserInfo;
- //拼接访问路径
- String url = String.format(WxConstant.URL_GET_OAUTH2_USER_INFO, accessToken, openId);
- //调用微信接口
- String response = HttpRequest.get(url).execute().body();
- log.info("url: {}\nresponse: {}", url, response);
- try {
- if (StrUtil.isEmpty(response) || null == (wxOauth2UserInfo = JacksonUtil.jsonToBean(response, WxOauth2UserInfo.class))) {
- throw new BaseException(WxCodeError.WX_HTTP_ERROR);
- }
- } catch (IOException e) {
- throw new BaseException(e.getMessage());
- }
- if (null != wxOauth2UserInfo.getErrcode()) {
- throw new BaseException(wxOauth2UserInfo.getErrcode(), wxOauth2UserInfo.getErrmsg());
- }
- if (StrUtil.isEmpty(wxOauth2UserInfo.getOpenId())) {
- throw new BaseException(WxCodeError.OPENID_ERROR);
- }
- return wxOauth2UserInfo;
- }
-}
+package com.ccsens.wechatutil.wxh5;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpRequest;
+import com.ccsens.util.DateUtil;
+import com.ccsens.util.JacksonUtil;
+import com.ccsens.util.exception.BaseException;
+import com.ccsens.wechatutil.bean.po.WxOauth2AccessToken;
+import com.ccsens.wechatutil.bean.po.WxOauth2UserInfo;
+import com.ccsens.wechatutil.util.WxCodeError;
+import com.ccsens.wechatutil.util.WxConstant;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+
+/**
+ * @author 逗
+ */
+@Slf4j
+@Component
+public class H5SigninUtil {
+
+ private static String appIdH5;
+ private static String secretH5;
+
+ @Value("${h5.appId:}")
+ public void setAppIdOfficial(String appIdOfficial) {
+ H5SigninUtil.appIdH5 = appIdOfficial;
+ }
+ @Value("${h5.secret:}")
+ public void setApplication(String secretOfficial) {
+ H5SigninUtil.secretH5 = secretOfficial;
+ }
+
+ public static WxOauth2UserInfo signinByH5(String code) {
+ return signinByH5(code, appIdH5, secretH5);
+ }
+
+ public static WxOauth2UserInfo signinByH5(String code, String appId, String secret) {
+ //获取accessToken
+ WxOauth2AccessToken wxOauth2AccessToken = getOauth2AccessToken(code, appId, secret);
+ //获取用户信息
+ return getOauth2UserInfo(wxOauth2AccessToken.getAccessToken(), wxOauth2AccessToken.getOpenId());
+ }
+
+ /**
+ * 获取网页授权凭证
+ * @param code OAuth2授权码
+ * @return WxOauth2AccessToken
+ */
+ private static WxOauth2AccessToken getOauth2AccessToken(String code, String appId, String secret) {
+ WxOauth2AccessToken wxOauth2AccessToken;
+ //拼接访问路径
+ String url = String.format(WxConstant.URL_GET_OAUTH2_ACCESS_TOKEN, appId, secret, code);
+ //调用微信接口
+ String response = HttpRequest.get(url).execute().body();
+ log.info("url: {}\nresponse: {}", url, response);
+ try {
+ if (StrUtil.isEmpty(response) || null == (wxOauth2AccessToken = JacksonUtil.jsonToBean(response, WxOauth2AccessToken.class))) {
+ throw new BaseException(WxCodeError.WX_HTTP_ERROR);
+ }
+ } catch (IOException e) {
+ throw new BaseException(e.getMessage());
+ }
+ if (null != wxOauth2AccessToken.getErrcode()) {
+ throw new BaseException(wxOauth2AccessToken.getErrcode(), wxOauth2AccessToken.getErrmsg());
+ }
+ if (StrUtil.isEmpty(wxOauth2AccessToken.getAccessToken())) {
+ throw new BaseException(WxCodeError.ACCESS_TOKEN_ERROR);
+ }
+ wxOauth2AccessToken.setCreatedAt(DateUtil.currentSeconds());
+ return wxOauth2AccessToken;
+ }
+
+ /**
+ * 通过网页授权accessToken获取用户信息
+ * @param accessToken 网页授权接口调用凭证
+ * @param openId 用户标识
+ * @return SNSUserInfo
+ */
+ private static WxOauth2UserInfo getOauth2UserInfo(String accessToken, String openId) {
+ WxOauth2UserInfo wxOauth2UserInfo;
+ //拼接访问路径
+ String url = String.format(WxConstant.URL_GET_OAUTH2_USER_INFO, accessToken, openId);
+ //调用微信接口
+ String response = HttpRequest.get(url).execute().body();
+ log.info("url: {}\nresponse: {}", url, response);
+ try {
+ if (StrUtil.isEmpty(response) || null == (wxOauth2UserInfo = JacksonUtil.jsonToBean(response, WxOauth2UserInfo.class))) {
+ throw new BaseException(WxCodeError.WX_HTTP_ERROR);
+ }
+ } catch (IOException e) {
+ throw new BaseException(e.getMessage());
+ }
+ if (null != wxOauth2UserInfo.getErrcode()) {
+ throw new BaseException(wxOauth2UserInfo.getErrcode(), wxOauth2UserInfo.getErrmsg());
+ }
+ if (StrUtil.isEmpty(wxOauth2UserInfo.getOpenId())) {
+ throw new BaseException(WxCodeError.OPENID_ERROR);
+ }
+ return wxOauth2UserInfo;
+ }
+}
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/wxmini/MiniCodeUtil.java b/util_wechat/src/main/java/com/ccsens/wechatutil/wxmini/MiniCodeUtil.java
similarity index 97%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/wxmini/MiniCodeUtil.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/wxmini/MiniCodeUtil.java
index d2b3060..7a5eb8e 100644
--- a/wechatutil/src/main/java/com/ccsens/wechatutil/wxmini/MiniCodeUtil.java
+++ b/util_wechat/src/main/java/com/ccsens/wechatutil/wxmini/MiniCodeUtil.java
@@ -1,159 +1,159 @@
-package com.ccsens.wechatutil.wxmini;
-
-import com.ccsens.util.HttpsUtil;
-import com.ccsens.util.JacksonUtil;
-import com.ccsens.util.exception.BaseException;
-import com.ccsens.wechatutil.bean.dto.WechatCode;
-import com.ccsens.wechatutil.bean.po.WxBaseEntity;
-import com.ccsens.wechatutil.util.WxCodeError;
-import com.ccsens.wechatutil.util.WxConstant;
-import com.ccsens.wechatutil.wxcommon.WxCommonUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import java.io.*;
-
-/**
- * @author 逗
- */
-@Slf4j
-@Component
-public class MiniCodeUtil {
-
- private static String miniAppId;
- private static String miniSecret;
-
- @Value("${mini.appId:}")
- public void setMiniAppId(String miniAppId) {
- MiniCodeUtil.miniAppId = miniAppId;
- }
- @Value("${mini.secret:}")
- public void setMiniSecret(String miniSecret) {
- MiniCodeUtil.miniSecret = miniSecret;
- }
- /**
- * 获取小程序码--方案A,可接受 path 参数较长,生成个数受限
- * 接口 A 加上接口 C,总共生成的码数量限制为 100,000,请谨慎调用。
- * 使用默认appId
- * @param wechatCodeA 传入参数
- * @param path 小程序码存储位置
- */
- public static void getWxCodeA(WechatCode.WechatCodeA wechatCodeA, String path)throws Exception {
- getWxCodeA(wechatCodeA,path,miniAppId,miniSecret);
- }
-
- /**
- * 获取小程序码--方案A,可接受 path 参数较长,生成个数受限
- * 接口 A 加上接口 C,总共生成的码数量限制为 100,000,请谨慎调用。
- * @param wechatCodeA 传入参数
- * @param path 小程序码存储位置
- * @param appId appId
- * @param secret secret
- */
- public static void getWxCodeA(WechatCode.WechatCodeA wechatCodeA, String path, String appId, String secret) throws Exception {
- String url = String.format(WxConstant.URL_GET_WX_CODE_A, WxCommonUtil.getAccessToken(appId, secret));
- log.info("调用生成二维码路径和accessToken:{}", url);
- String postStr = JacksonUtil.beanToJson(wechatCodeA);
- log.info("二维码的参数:{}", postStr);
- //调用微信接口在指定位置生成图片
- httpWxCode(path, url, postStr);
- }
-
- /**
- * 获取小程序码--方案B,可接受页面参数较短,生成个数不受限。
- * 接口 B 调用分钟频率受限(5000次/分钟),如需大量小程序码,建议预生成
- * 使用默认appId
- * @param wechatCodeB 传入参数
- * @param path 小程序码存储位置
- */
- public static void getWxCodeB(WechatCode.WechatCodeB wechatCodeB, String path)throws Exception {
- getWxCodeB(wechatCodeB,path,miniAppId, miniSecret);
- }
-
- /**
- * 获取小程序码--方案B,可接受页面参数较短,生成个数不受限。
- * 接口 B 调用分钟频率受限(5000次/分钟),如需大量小程序码,建议预生成
- * @param wechatCodeB 传入参数
- * @param path 小程序码存储位置
- * @param appId appId
- * @param secret secret
- */
- public static void getWxCodeB(WechatCode.WechatCodeB wechatCodeB, String path, String appId, String secret) throws Exception {
- String url = String.format(WxConstant.URL_GET_WX_CODE_B, WxCommonUtil.getAccessToken(appId, secret));
- log.info("调用生成二维码路径和accessToken:{}", url);
- String postStr = JacksonUtil.beanToJson(wechatCodeB);
- log.info("二维码的参数:{}", postStr);
- //调用微信接口在指定位置生成图片
- httpWxCode(path, url, postStr);
- }
-
- /**
- * 方案C-生成小程序码(二维码),可接受 path 参数较长,生成个数受限,数量限制见
- * 接口 A 加上接口 C,总共生成的码数量限制为 100,000,请谨慎调用。
- * 使用默认appId
- * @param wechatCodeC 传入参数
- * @param path 小程序码存储位置
- */
- public static void getWxCodeC(WechatCode.WechatCodeC wechatCodeC, String path) throws Exception {
- getWxCodeC(wechatCodeC,path,miniAppId, miniSecret);
- }
-
- /**
- * 方案C-生成小程序码(二维码),可接受 path 参数较长,生成个数受限,数量限制见
- * 接口 A 加上接口 C,总共生成的码数量限制为 100,000,请谨慎调用。
- * @param wechatCodeC 传入参数
- * @param path 小程序码存储位置
- * @param appId appId
- * @param secret secret
- */
- public static void getWxCodeC(WechatCode.WechatCodeC wechatCodeC, String path, String appId, String secret) throws Exception {
- String url = String.format(WxConstant.URL_GET_WX_CODE_C, WxCommonUtil.getAccessToken(appId, secret));
- log.info("调用生成二维码路径和accessToken:{}", url);
- String postStr = JacksonUtil.beanToJson(wechatCodeC);
- log.info("二维码的参数:{}", postStr);
- //调用微信接口在指定位置生成图片
- httpWxCode(path, url, postStr);
- }
-
- /**
- * 调用微信的接口在指定位置生成二维码
- * @param path 图片储存位置
- * @param url 微信接口路径
- * @param postStr 传入参数
- * @throws Exception 异常
- */
- public static void httpWxCode(String path, String url, String postStr) throws Exception {
- WxBaseEntity wxBaseEntity;
- byte[] response = HttpsUtil.httpsRequestByte(url, "POST", postStr);
-
- if(response.length == 0){
- throw new BaseException(WxCodeError.WX_HTTP_ERROR);
- }
- try {
- if (null == (wxBaseEntity = JacksonUtil.jsonToBean(new String(response), WxBaseEntity.class))) {
- throw new BaseException(WxCodeError.WX_HTTP_ERROR);
- }
- if (null != wxBaseEntity.getErrcode()) {
- throw new BaseException(wxBaseEntity.getErrcode(), wxBaseEntity.getErrmsg());
- }
- } catch (IOException e) {
- // 从输入流读取返回内容
- File file = new File(path);
- if (!file.getParentFile().exists()) {
- file.getParentFile().mkdirs();
- }
- InputStream inputStream = new ByteArrayInputStream(response);
- BufferedInputStream bis = new BufferedInputStream(inputStream);
- OutputStream os = new FileOutputStream(file);
- int len;
- byte[] arr = new byte[1024];
- while ((len = bis.read(arr)) != -1)
- {
- os.write(arr, 0, len);
- os.flush();
- }
- os.close();
- }
- }
-}
+package com.ccsens.wechatutil.wxmini;
+
+import com.ccsens.util.HttpsUtil;
+import com.ccsens.util.JacksonUtil;
+import com.ccsens.util.exception.BaseException;
+import com.ccsens.wechatutil.bean.dto.WechatCode;
+import com.ccsens.wechatutil.bean.po.WxBaseEntity;
+import com.ccsens.wechatutil.util.WxCodeError;
+import com.ccsens.wechatutil.util.WxConstant;
+import com.ccsens.wechatutil.wxcommon.WxCommonUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.*;
+
+/**
+ * @author 逗
+ */
+@Slf4j
+@Component
+public class MiniCodeUtil {
+
+ private static String miniAppId;
+ private static String miniSecret;
+
+ @Value("${mini.appId:}")
+ public void setMiniAppId(String miniAppId) {
+ MiniCodeUtil.miniAppId = miniAppId;
+ }
+ @Value("${mini.secret:}")
+ public void setMiniSecret(String miniSecret) {
+ MiniCodeUtil.miniSecret = miniSecret;
+ }
+ /**
+ * 获取小程序码--方案A,可接受 path 参数较长,生成个数受限
+ * 接口 A 加上接口 C,总共生成的码数量限制为 100,000,请谨慎调用。
+ * 使用默认appId
+ * @param wechatCodeA 传入参数
+ * @param path 小程序码存储位置
+ */
+ public static void getWxCodeA(WechatCode.WechatCodeA wechatCodeA, String path)throws Exception {
+ getWxCodeA(wechatCodeA,path,miniAppId,miniSecret);
+ }
+
+ /**
+ * 获取小程序码--方案A,可接受 path 参数较长,生成个数受限
+ * 接口 A 加上接口 C,总共生成的码数量限制为 100,000,请谨慎调用。
+ * @param wechatCodeA 传入参数
+ * @param path 小程序码存储位置
+ * @param appId appId
+ * @param secret secret
+ */
+ public static void getWxCodeA(WechatCode.WechatCodeA wechatCodeA, String path, String appId, String secret) throws Exception {
+ String url = String.format(WxConstant.URL_GET_WX_CODE_A, WxCommonUtil.getAccessToken(appId, secret));
+ log.info("调用生成二维码路径和accessToken:{}", url);
+ String postStr = JacksonUtil.beanToJson(wechatCodeA);
+ log.info("二维码的参数:{}", postStr);
+ //调用微信接口在指定位置生成图片
+ httpWxCode(path, url, postStr);
+ }
+
+ /**
+ * 获取小程序码--方案B,可接受页面参数较短,生成个数不受限。
+ * 接口 B 调用分钟频率受限(5000次/分钟),如需大量小程序码,建议预生成
+ * 使用默认appId
+ * @param wechatCodeB 传入参数
+ * @param path 小程序码存储位置
+ */
+ public static void getWxCodeB(WechatCode.WechatCodeB wechatCodeB, String path)throws Exception {
+ getWxCodeB(wechatCodeB,path,miniAppId, miniSecret);
+ }
+
+ /**
+ * 获取小程序码--方案B,可接受页面参数较短,生成个数不受限。
+ * 接口 B 调用分钟频率受限(5000次/分钟),如需大量小程序码,建议预生成
+ * @param wechatCodeB 传入参数
+ * @param path 小程序码存储位置
+ * @param appId appId
+ * @param secret secret
+ */
+ public static void getWxCodeB(WechatCode.WechatCodeB wechatCodeB, String path, String appId, String secret) throws Exception {
+ String url = String.format(WxConstant.URL_GET_WX_CODE_B, WxCommonUtil.getAccessToken(appId, secret));
+ log.info("调用生成二维码路径和accessToken:{}", url);
+ String postStr = JacksonUtil.beanToJson(wechatCodeB);
+ log.info("二维码的参数:{}", postStr);
+ //调用微信接口在指定位置生成图片
+ httpWxCode(path, url, postStr);
+ }
+
+ /**
+ * 方案C-生成小程序码(二维码),可接受 path 参数较长,生成个数受限,数量限制见
+ * 接口 A 加上接口 C,总共生成的码数量限制为 100,000,请谨慎调用。
+ * 使用默认appId
+ * @param wechatCodeC 传入参数
+ * @param path 小程序码存储位置
+ */
+ public static void getWxCodeC(WechatCode.WechatCodeC wechatCodeC, String path) throws Exception {
+ getWxCodeC(wechatCodeC,path,miniAppId, miniSecret);
+ }
+
+ /**
+ * 方案C-生成小程序码(二维码),可接受 path 参数较长,生成个数受限,数量限制见
+ * 接口 A 加上接口 C,总共生成的码数量限制为 100,000,请谨慎调用。
+ * @param wechatCodeC 传入参数
+ * @param path 小程序码存储位置
+ * @param appId appId
+ * @param secret secret
+ */
+ public static void getWxCodeC(WechatCode.WechatCodeC wechatCodeC, String path, String appId, String secret) throws Exception {
+ String url = String.format(WxConstant.URL_GET_WX_CODE_C, WxCommonUtil.getAccessToken(appId, secret));
+ log.info("调用生成二维码路径和accessToken:{}", url);
+ String postStr = JacksonUtil.beanToJson(wechatCodeC);
+ log.info("二维码的参数:{}", postStr);
+ //调用微信接口在指定位置生成图片
+ httpWxCode(path, url, postStr);
+ }
+
+ /**
+ * 调用微信的接口在指定位置生成二维码
+ * @param path 图片储存位置
+ * @param url 微信接口路径
+ * @param postStr 传入参数
+ * @throws Exception 异常
+ */
+ public static void httpWxCode(String path, String url, String postStr) throws Exception {
+ WxBaseEntity wxBaseEntity;
+ byte[] response = HttpsUtil.httpsRequestByte(url, "POST", postStr);
+
+ if(response.length == 0){
+ throw new BaseException(WxCodeError.WX_HTTP_ERROR);
+ }
+ try {
+ if (null == (wxBaseEntity = JacksonUtil.jsonToBean(new String(response), WxBaseEntity.class))) {
+ throw new BaseException(WxCodeError.WX_HTTP_ERROR);
+ }
+ if (null != wxBaseEntity.getErrcode()) {
+ throw new BaseException(wxBaseEntity.getErrcode(), wxBaseEntity.getErrmsg());
+ }
+ } catch (IOException e) {
+ // 从输入流读取返回内容
+ File file = new File(path);
+ if (!file.getParentFile().exists()) {
+ file.getParentFile().mkdirs();
+ }
+ InputStream inputStream = new ByteArrayInputStream(response);
+ BufferedInputStream bis = new BufferedInputStream(inputStream);
+ OutputStream os = new FileOutputStream(file);
+ int len;
+ byte[] arr = new byte[1024];
+ while ((len = bis.read(arr)) != -1)
+ {
+ os.write(arr, 0, len);
+ os.flush();
+ }
+ os.close();
+ }
+ }
+}
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/wxmini/MiniCustomSendUtil.java b/util_wechat/src/main/java/com/ccsens/wechatutil/wxmini/MiniCustomSendUtil.java
similarity index 100%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/wxmini/MiniCustomSendUtil.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/wxmini/MiniCustomSendUtil.java
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/wxmini/MiniEncryptionAndDecryptionUtil.java b/util_wechat/src/main/java/com/ccsens/wechatutil/wxmini/MiniEncryptionAndDecryptionUtil.java
similarity index 100%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/wxmini/MiniEncryptionAndDecryptionUtil.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/wxmini/MiniEncryptionAndDecryptionUtil.java
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/wxmini/MiniMessageUtil.java b/util_wechat/src/main/java/com/ccsens/wechatutil/wxmini/MiniMessageUtil.java
similarity index 97%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/wxmini/MiniMessageUtil.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/wxmini/MiniMessageUtil.java
index cd071c5..83c07df 100644
--- a/wechatutil/src/main/java/com/ccsens/wechatutil/wxmini/MiniMessageUtil.java
+++ b/util_wechat/src/main/java/com/ccsens/wechatutil/wxmini/MiniMessageUtil.java
@@ -1,91 +1,91 @@
-package com.ccsens.wechatutil.wxmini;
-
-import com.ccsens.util.HttpsUtil;
-import com.ccsens.wechatutil.bean.dto.WxMessageDto;
-import com.ccsens.wechatutil.util.WxConstant;
-import com.ccsens.wechatutil.wxcommon.WxCommonUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-
-/**
- * @author 逗
- */
-@Slf4j
-@Component
-public class MiniMessageUtil {
-
- private static String miniAppId;
- private static String miniSecret;
-
- @Value("${mini.appId:}")
- public void setMiniAppId(String miniAppId) {
- MiniMessageUtil.miniAppId = miniAppId;
- }
- @Value("${mini.secret:}")
- public void setMiniSecret(String miniSecret) {
- MiniMessageUtil.miniSecret = miniSecret;
- }
-
- /**
- * 发送微信订阅消息 (使用默认appId)
- *
- * @param notifyType 通知类型
- * @param toUser 用户openid
- * @param page 小程序页面路径
- * @param params 小程序模板数据
- */
- public static boolean sendSubcribeMsg(WxConstant.Packet_Notify_Type notifyType, String toUser, String page, List params) throws Exception {
- return sendSubcribeMsg(notifyType,toUser,page,params,miniAppId,miniSecret);
- }
-
- /**
- * 发送微信订阅消息
- *
- * @param notifyType 通知类型
- * @param toUser 用户openid
- * @param page 小程序页面路径
- * @param params 小程序模板数据
- */
- public static boolean sendSubcribeMsg(WxConstant.Packet_Notify_Type notifyType, String toUser, String page, List params,String appId, String secret) throws Exception {
- String ret = null;
- String url = String.format(WxConstant.URL_SEND_SUBSCRIBE_MESSAGE, WxCommonUtil.getAccessToken(appId, secret));
- switch (notifyType) {
- //订单支付成功通知
- case Buy: {
- WxMessageDto.SubscribeEntity t = new WxMessageDto.SubscribeEntity<>();
- t.setTouser(toUser);
- t.setTemplate_id(WxConstant.SUBSCRIBE_MSG_ID_BUY);
- t.setPage(page);
- t.setData(new WxMessageDto.ReceiveSubscriBuyData(params));
- System.out.println(com.ccsens.wechatutil.payutil.JacksonUtil.beanToJson(t));
- ret = HttpsUtil.httpsRequest(url, "POST", com.ccsens.wechatutil.payutil.JacksonUtil.beanToJson(t));
- break;
- }
- //订单发货
- case ReceiveSubscriBuyData: {
- WxMessageDto.SubscribeEntity t = new WxMessageDto.SubscribeEntity<>();
- t.setTouser(toUser);
- t.setTemplate_id(WxConstant.SUBSCRIBE_MSG_ID_ORDERSEND);
- t.setData(new WxMessageDto.ReceiveSubscriOrderSendData(params));
- System.out.println(com.ccsens.wechatutil.payutil.JacksonUtil.beanToJson(t));
- ret = HttpsUtil.httpsRequest(url, "POST", com.ccsens.wechatutil.payutil.JacksonUtil.beanToJson(t));
- break;
- }
- default: {
- break;
- }
- }
- //ok: {"errcode":0,"errmsg":"ok"}
- //err: {"errcode":43101,"errmsg":"user refuse to accept the msg hint: [V_GEdA02503942]"}
- System.out.println("Send Subscribe Message:" + ret);
- String errCode = com.ccsens.wechatutil.payutil.JacksonUtil.getJsonValue(ret, "errcode");
- System.out.println(errCode);
- return "0".equals(errCode);
- }
-
-
-
-}
+package com.ccsens.wechatutil.wxmini;
+
+import com.ccsens.util.HttpsUtil;
+import com.ccsens.wechatutil.bean.dto.WxMessageDto;
+import com.ccsens.wechatutil.util.WxConstant;
+import com.ccsens.wechatutil.wxcommon.WxCommonUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @author 逗
+ */
+@Slf4j
+@Component
+public class MiniMessageUtil {
+
+ private static String miniAppId;
+ private static String miniSecret;
+
+ @Value("${mini.appId:}")
+ public void setMiniAppId(String miniAppId) {
+ MiniMessageUtil.miniAppId = miniAppId;
+ }
+ @Value("${mini.secret:}")
+ public void setMiniSecret(String miniSecret) {
+ MiniMessageUtil.miniSecret = miniSecret;
+ }
+
+ /**
+ * 发送微信订阅消息 (使用默认appId)
+ *
+ * @param notifyType 通知类型
+ * @param toUser 用户openid
+ * @param page 小程序页面路径
+ * @param params 小程序模板数据
+ */
+ public static boolean sendSubcribeMsg(WxConstant.Packet_Notify_Type notifyType, String toUser, String page, List params) throws Exception {
+ return sendSubcribeMsg(notifyType,toUser,page,params,miniAppId,miniSecret);
+ }
+
+ /**
+ * 发送微信订阅消息
+ *
+ * @param notifyType 通知类型
+ * @param toUser 用户openid
+ * @param page 小程序页面路径
+ * @param params 小程序模板数据
+ */
+ public static boolean sendSubcribeMsg(WxConstant.Packet_Notify_Type notifyType, String toUser, String page, List params,String appId, String secret) throws Exception {
+ String ret = null;
+ String url = String.format(WxConstant.URL_SEND_SUBSCRIBE_MESSAGE, WxCommonUtil.getAccessToken(appId, secret));
+ switch (notifyType) {
+ //订单支付成功通知
+ case Buy: {
+ WxMessageDto.SubscribeEntity t = new WxMessageDto.SubscribeEntity<>();
+ t.setTouser(toUser);
+ t.setTemplate_id(WxConstant.SUBSCRIBE_MSG_ID_BUY);
+ t.setPage(page);
+ t.setData(new WxMessageDto.ReceiveSubscriBuyData(params));
+ System.out.println(com.ccsens.wechatutil.payutil.JacksonUtil.beanToJson(t));
+ ret = HttpsUtil.httpsRequest(url, "POST", com.ccsens.wechatutil.payutil.JacksonUtil.beanToJson(t));
+ break;
+ }
+ //订单发货
+ case ReceiveSubscriBuyData: {
+ WxMessageDto.SubscribeEntity t = new WxMessageDto.SubscribeEntity<>();
+ t.setTouser(toUser);
+ t.setTemplate_id(WxConstant.SUBSCRIBE_MSG_ID_ORDERSEND);
+ t.setData(new WxMessageDto.ReceiveSubscriOrderSendData(params));
+ System.out.println(com.ccsens.wechatutil.payutil.JacksonUtil.beanToJson(t));
+ ret = HttpsUtil.httpsRequest(url, "POST", com.ccsens.wechatutil.payutil.JacksonUtil.beanToJson(t));
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ //ok: {"errcode":0,"errmsg":"ok"}
+ //err: {"errcode":43101,"errmsg":"user refuse to accept the msg hint: [V_GEdA02503942]"}
+ System.out.println("Send Subscribe Message:" + ret);
+ String errCode = com.ccsens.wechatutil.payutil.JacksonUtil.getJsonValue(ret, "errcode");
+ System.out.println(errCode);
+ return "0".equals(errCode);
+ }
+
+
+
+}
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/wxmini/MiniSigninUtil.java b/util_wechat/src/main/java/com/ccsens/wechatutil/wxmini/MiniSigninUtil.java
similarity index 97%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/wxmini/MiniSigninUtil.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/wxmini/MiniSigninUtil.java
index f744c1f..6c0af31 100644
--- a/wechatutil/src/main/java/com/ccsens/wechatutil/wxmini/MiniSigninUtil.java
+++ b/util_wechat/src/main/java/com/ccsens/wechatutil/wxmini/MiniSigninUtil.java
@@ -1,81 +1,81 @@
-package com.ccsens.wechatutil.wxmini;
-
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.http.HttpRequest;
-import com.ccsens.util.HttpsUtil;
-import com.ccsens.util.JacksonUtil;
-import com.ccsens.util.exception.BaseException;
-import com.ccsens.wechatutil.bean.dto.WechatCode;
-import com.ccsens.wechatutil.bean.dto.WxMessageDto;
-import com.ccsens.wechatutil.bean.po.MiniProgramUser;
-import com.ccsens.wechatutil.bean.po.WxBaseEntity;
-import com.ccsens.wechatutil.util.WxCodeError;
-import com.ccsens.wechatutil.util.WxConstant;
-import com.ccsens.wechatutil.wxcommon.WxCommonUtil;
-import com.ccsens.wechatutil.wxofficial.OfficialAccountSigninUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import java.io.*;
-import java.util.List;
-
-/**
- * @author 逗
- */
-@Slf4j
-@Component
-public class MiniSigninUtil {
-
- private static String miniAppId;
- private static String miniSecret;
-
- @Value("${mini.appId:}")
- public void setMiniAppId(String miniAppId) {
- MiniSigninUtil.miniAppId = miniAppId;
- }
- @Value("${mini.secret:}")
- public void setMiniSecret(String miniSecret) {
- MiniSigninUtil.miniSecret = miniSecret;
- }
-
-
- /**
- * 小程序登录
- * -- 从配置文件中获取默认appId
- * 配置文件内的名称 h5.appId: 和 h5.secret:
- * @param code code
- * @return 返回当前用户的openId等
- */
- public static MiniProgramUser signinByMini(String code) {
- return signinByMini(code, miniAppId, miniSecret);
- }
- /**
- * 小程序登录 -- 传入appId
- * @param code code
- * @param appId appId
- * @param secret secret
- * @return 返回当前用户的openId等
- */
- public static MiniProgramUser signinByMini(String code, String appId, String secret) {
- MiniProgramUser wxUser;
- //拼接wx的访问的路径
- String url = String.format(WxConstant.MINI_PROGRAM_LOGIN, appId, secret, code, WxConstant.GRANT_TYPE);
- //调用微信的接口
- String response = HttpRequest.get(url).execute().body();
- log.info("url: {}\nresponse: {}", url, response);
- try {
- if (StrUtil.isEmpty(response) || null == (wxUser = JacksonUtil.jsonToBean(response, MiniProgramUser.class))) {
- throw new BaseException(WxCodeError.WX_HTTP_ERROR);
- }
- } catch (IOException e) {
- throw new BaseException(e.getMessage());
- }
- if (null != wxUser.getErrcode()) {
- throw new BaseException(wxUser.getErrcode(), wxUser.getErrmsg());
- }
- return wxUser;
- }
-
-
-}
+package com.ccsens.wechatutil.wxmini;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpRequest;
+import com.ccsens.util.HttpsUtil;
+import com.ccsens.util.JacksonUtil;
+import com.ccsens.util.exception.BaseException;
+import com.ccsens.wechatutil.bean.dto.WechatCode;
+import com.ccsens.wechatutil.bean.dto.WxMessageDto;
+import com.ccsens.wechatutil.bean.po.MiniProgramUser;
+import com.ccsens.wechatutil.bean.po.WxBaseEntity;
+import com.ccsens.wechatutil.util.WxCodeError;
+import com.ccsens.wechatutil.util.WxConstant;
+import com.ccsens.wechatutil.wxcommon.WxCommonUtil;
+import com.ccsens.wechatutil.wxofficial.OfficialAccountSigninUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.*;
+import java.util.List;
+
+/**
+ * @author 逗
+ */
+@Slf4j
+@Component
+public class MiniSigninUtil {
+
+ private static String miniAppId;
+ private static String miniSecret;
+
+ @Value("${mini.appId:}")
+ public void setMiniAppId(String miniAppId) {
+ MiniSigninUtil.miniAppId = miniAppId;
+ }
+ @Value("${mini.secret:}")
+ public void setMiniSecret(String miniSecret) {
+ MiniSigninUtil.miniSecret = miniSecret;
+ }
+
+
+ /**
+ * 小程序登录
+ * -- 从配置文件中获取默认appId
+ * 配置文件内的名称 h5.appId: 和 h5.secret:
+ * @param code code
+ * @return 返回当前用户的openId等
+ */
+ public static MiniProgramUser signinByMini(String code) {
+ return signinByMini(code, miniAppId, miniSecret);
+ }
+ /**
+ * 小程序登录 -- 传入appId
+ * @param code code
+ * @param appId appId
+ * @param secret secret
+ * @return 返回当前用户的openId等
+ */
+ public static MiniProgramUser signinByMini(String code, String appId, String secret) {
+ MiniProgramUser wxUser;
+ //拼接wx的访问的路径
+ String url = String.format(WxConstant.MINI_PROGRAM_LOGIN, appId, secret, code, WxConstant.GRANT_TYPE);
+ //调用微信的接口
+ String response = HttpRequest.get(url).execute().body();
+ log.info("url: {}\nresponse: {}", url, response);
+ try {
+ if (StrUtil.isEmpty(response) || null == (wxUser = JacksonUtil.jsonToBean(response, MiniProgramUser.class))) {
+ throw new BaseException(WxCodeError.WX_HTTP_ERROR);
+ }
+ } catch (IOException e) {
+ throw new BaseException(e.getMessage());
+ }
+ if (null != wxUser.getErrcode()) {
+ throw new BaseException(wxUser.getErrcode(), wxUser.getErrmsg());
+ }
+ return wxUser;
+ }
+
+
+}
diff --git a/wechatutil/src/main/java/com/ccsens/wechatutil/wxofficial/OfficialAccountMessageUtil.java b/util_wechat/src/main/java/com/ccsens/wechatutil/wxofficial/OfficialAccountMessageUtil.java
similarity index 97%
rename from wechatutil/src/main/java/com/ccsens/wechatutil/wxofficial/OfficialAccountMessageUtil.java
rename to util_wechat/src/main/java/com/ccsens/wechatutil/wxofficial/OfficialAccountMessageUtil.java
index 9525d65..7a86829 100644
--- a/wechatutil/src/main/java/com/ccsens/wechatutil/wxofficial/OfficialAccountMessageUtil.java
+++ b/util_wechat/src/main/java/com/ccsens/wechatutil/wxofficial/OfficialAccountMessageUtil.java
@@ -1,123 +1,123 @@
-package com.ccsens.wechatutil.wxofficial;
-
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.util.StrUtil;
-import com.ccsens.util.*;
-import com.ccsens.util.exception.BaseException;
-import com.ccsens.wechatutil.bean.dto.WxTemplateMessage;
-import com.ccsens.wechatutil.bean.po.WxBaseEntity;
-import com.ccsens.wechatutil.util.WxCodeError;
-import com.ccsens.wechatutil.util.WxConstant;
-import com.ccsens.wechatutil.wxcommon.WxCommonUtil;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * @author 逗
- */
-@Slf4j
-@Component
-public class OfficialAccountMessageUtil {
-
-
- private static String appIdOfficial;
- private static String secretOfficial;
-
- @Value("${official.appId:}")
- public void setAppIdOfficial(String appIdOfficial) {
- OfficialAccountMessageUtil.appIdOfficial = appIdOfficial;
- }
- @Value("${official.secret:}")
- public void setApplication(String secretOfficial) {
- OfficialAccountMessageUtil.secretOfficial = secretOfficial;
- }
-
-// public static void officialMessage() {
-// WxTemplateMessage message = new WxTemplateMessage();
-//
-// String url = String.format(WechatUtil.PROJECT_URL, 123);
-//// WxTemplateMessage.MiniProgram miniProgram = new WxTemplateMessage.MiniProgram(WechatUtil.appid,url);
-//
-//// message.setMiniprogram(miniProgram);
-//
-//
-// message.setTemplate_id(WxGzhUtil.Template.TASK_FINISH.templateId);
-//// WxTemplateMessage.TemplateData data = new WxTemplateMessage.TemplateData();
-//// data.setFirst(new WxTemplateMessage.TemplateSettings("测试项目"));
-//// data.setKeyword1(new WxTemplateMessage.TemplateSettings("测试任务"));
-//// data.setKeyword2(new WxTemplateMessage.TemplateSettings(DateUtil.now()));
-//
-// Map data = new HashMap<>();
-// data.put("zzz", new WxTemplateMessage.TemplateSettings("测试fzz"));
-// data.put("first", new WxTemplateMessage.TemplateSettings("测试first"));
-// data.put("keyword1", new WxTemplateMessage.TemplateSettings("测试keyword1"));
-// data.put("keyword2", new WxTemplateMessage.TemplateSettings("测试keyword2"));
-// data.put("remark", new WxTemplateMessage.TemplateSettings("测试remark"));
-//
-// message.setData(data);
-//
-// List openIdList = new ArrayList<>();
-// openIdList.add("oALvgw-_70_fXptB97xJpYDhMJRU");
-//
-// officialMessage(message,openIdList);
-// }
-
- /**
- * 公众号发送订阅消息(使用默认openId)
- * @param templateMessage 消息
- * @param openIdList 推送的用户
- */
- public static void officialMessage(WxTemplateMessage templateMessage, List openIdList) {
- officialMessage(templateMessage,openIdList,appIdOfficial, secretOfficial);
- }
-
- /**
- * 公众号发送订阅消息(传入openId)
- * @param templateMessage 消息
- * @param openIdList 推送的用户
- */
- public static void officialMessage(WxTemplateMessage templateMessage, List openIdList,String appId, String secret) {
- //判断是否有openId
- if (CollectionUtil.isNotEmpty(openIdList)) {
- openIdList.forEach(openid -> {
- //拼接访问路径
- sendMsg(appId, secret, templateMessage);
- });
- }
- }
-
- /**
- * 公众号发送订阅消息(传入openId)
- * @param templateMessages 消息
- */
- public static void officialMessage(List templateMessages, String appId, String secret) {
- //判断是否有openId
- if (CollectionUtil.isEmpty(templateMessages)) {
- return;
- }
- templateMessages.forEach(templateMessage -> sendMsg(appId, secret, templateMessage));
- }
-
- private static void sendMsg(String appId, String secret, WxTemplateMessage templateMessage) {
- //拼接访问路径
- String url = String.format(WxConstant.MESSAGE_TEMPLATE_SEND, WxCommonUtil.getAccessToken(appId, secret));
- //调用微信接口
- String response = RestTemplateUtil.postBody(url, templateMessage);
- log.info("url: {}\nresponse: {}", url, response);
- WxBaseEntity wxBaseEntity;
- try {
- if (StrUtil.isEmpty(response) || null == (wxBaseEntity = JacksonUtil.jsonToBean(response, WxBaseEntity.class))) {
- throw new BaseException(WxCodeError.WX_HTTP_ERROR);
- }
- } catch (IOException e) {
- throw new BaseException(e.getMessage());
- }
- if (null != wxBaseEntity.getErrcode()) {
- throw new BaseException(wxBaseEntity.getErrcode(), wxBaseEntity.getErrmsg());
- }
- }
-}
+package com.ccsens.wechatutil.wxofficial;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
+import com.ccsens.util.*;
+import com.ccsens.util.exception.BaseException;
+import com.ccsens.wechatutil.bean.dto.WxTemplateMessage;
+import com.ccsens.wechatutil.bean.po.WxBaseEntity;
+import com.ccsens.wechatutil.util.WxCodeError;
+import com.ccsens.wechatutil.util.WxConstant;
+import com.ccsens.wechatutil.wxcommon.WxCommonUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author 逗
+ */
+@Slf4j
+@Component
+public class OfficialAccountMessageUtil {
+
+
+ private static String appIdOfficial;
+ private static String secretOfficial;
+
+ @Value("${official.appId:}")
+ public void setAppIdOfficial(String appIdOfficial) {
+ OfficialAccountMessageUtil.appIdOfficial = appIdOfficial;
+ }
+ @Value("${official.secret:}")
+ public void setApplication(String secretOfficial) {
+ OfficialAccountMessageUtil.secretOfficial = secretOfficial;
+ }
+
+// public static void officialMessage() {
+// WxTemplateMessage message = new WxTemplateMessage();
+//
+// String url = String.format(WechatUtil.PROJECT_URL, 123);
+//// WxTemplateMessage.MiniProgram miniProgram = new WxTemplateMessage.MiniProgram(WechatUtil.appid,url);
+//
+//// message.setMiniprogram(miniProgram);
+//
+//
+// message.setTemplate_id(WxGzhUtil.Template.TASK_FINISH.templateId);
+//// WxTemplateMessage.TemplateData data = new WxTemplateMessage.TemplateData();
+//// data.setFirst(new WxTemplateMessage.TemplateSettings("测试项目"));
+//// data.setKeyword1(new WxTemplateMessage.TemplateSettings("测试任务"));
+//// data.setKeyword2(new WxTemplateMessage.TemplateSettings(DateUtil.now()));
+//
+// Map data = new HashMap<>();
+// data.put("zzz", new WxTemplateMessage.TemplateSettings("测试fzz"));
+// data.put("first", new WxTemplateMessage.TemplateSettings("测试first"));
+// data.put("keyword1", new WxTemplateMessage.TemplateSettings("测试keyword1"));
+// data.put("keyword2", new WxTemplateMessage.TemplateSettings("测试keyword2"));
+// data.put("remark", new WxTemplateMessage.TemplateSettings("测试remark"));
+//
+// message.setData(data);
+//
+// List openIdList = new ArrayList<>();
+// openIdList.add("oALvgw-_70_fXptB97xJpYDhMJRU");
+//
+// officialMessage(message,openIdList);
+// }
+
+ /**
+ * 公众号发送订阅消息(使用默认openId)
+ * @param templateMessage 消息
+ * @param openIdList 推送的用户
+ */
+ public static void officialMessage(WxTemplateMessage templateMessage, List