diff --git a/hai-cweb/src/main/java/com/cweb/config/AuthConfig.java b/hai-cweb/src/main/java/com/cweb/config/AuthConfig.java index e795a16c..064875c4 100644 --- a/hai-cweb/src/main/java/com/cweb/config/AuthConfig.java +++ b/hai-cweb/src/main/java/com/cweb/config/AuthConfig.java @@ -106,6 +106,7 @@ public class AuthConfig implements WebMvcConfigurer { .excludePathPatterns("/sms/getSmsCode") .excludePathPatterns("/user/login") .excludePathPatterns("/user/getUnionId") + .excludePathPatterns("/order/orderToH5Pay") .excludePathPatterns("/wechat/*") ; } diff --git a/hai-cweb/src/main/java/com/cweb/controller/pay/OrderController.java b/hai-cweb/src/main/java/com/cweb/controller/pay/OrderController.java index 0243f904..1ba43b8d 100644 --- a/hai-cweb/src/main/java/com/cweb/controller/pay/OrderController.java +++ b/hai-cweb/src/main/java/com/cweb/controller/pay/OrderController.java @@ -1,5 +1,6 @@ package com.cweb.controller.pay; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.cweb.config.SysConst; import com.hai.common.exception.ErrorCode; @@ -9,8 +10,10 @@ import com.hai.common.pay.WechatPayUtil; import com.hai.common.pay.entity.OrderType; import com.hai.common.pay.entity.WeChatPayReqInfo; import com.hai.common.pay.util.MD5Util; +import com.hai.common.security.Base64Util; import com.hai.common.security.SessionObject; import com.hai.common.security.UserCenter; +import com.hai.common.utils.HttpsUtils; import com.hai.common.utils.MathUtils; import com.hai.common.utils.ResponseMsgUtil; import com.hai.entity.HighChildOrder; @@ -21,9 +24,21 @@ import com.hai.model.ResponseData; import com.hai.model.UserInfoModel; import com.hai.service.HighCouponService; import com.hai.service.HighOrderService; +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 io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -35,10 +50,11 @@ import org.springframework.web.bind.annotation.ResponseBody; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; +import java.io.*; import java.math.BigDecimal; -import java.util.HashMap; -import java.util.Map; -import java.util.SortedMap; +import java.security.*; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.*; import java.util.concurrent.ThreadLocalRandom; /** @@ -207,4 +223,84 @@ public class OrderController { return ResponseMsgUtil.exception(e); } } + + @RequestMapping(value="/orderToH5Pay",method = RequestMethod.POST) + @ResponseBody + @ApiOperation(value = "H5订单下单") + public ResponseData orderToH5Pay(@RequestBody String reqBodyStr) { + try { + /* if (StringUtils.isBlank(reqBodyStr)) { + log.error("orderToPay error!", "参数错误"); + throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, ""); + } + JSONObject jsonObject = JSONObject.parseObject(reqBodyStr); + Long orderId = jsonObject.getLong("orderId"); + if ( orderId == null) { + log.error("orderToPay error!", "参数错误"); + throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, ""); + }*/ + + Map param = new HashMap<>(); + param.put("appid", SysConst.getSysConfig().getWxMchAppId()); + param.put("mchid", SysConst.getSysConfig().getWxSubMchId()); + param.put("description", "购买商品"); + param.put("out_trade_no", String.valueOf(new Date().getTime())); + param.put("notify_url", SysConst.getSysConfig().getNotifyUrl()); + + Map amountMap = new HashMap<>(); + amountMap.put("total", 1); + param.put("amount", amountMap); + + Map sceneInfoMap = new HashMap<>(); + sceneInfoMap.put("payer_client_ip", "127.0.0.1"); + + Map h5InfoMap = new HashMap<>(); + h5InfoMap.put("type", "Wap"); + sceneInfoMap.put("h5_info", h5InfoMap); + + param.put("scene_info", sceneInfoMap); + + Map header = new HashMap<>(); + String post = getToken("POST", "/v3/pay/transactions/h5", JSONObject.toJSONString(param)); + header.put("Accept","application/json"); + header.put("Authorization", "WECHATPAY2-SHA256-RSA2048 " + post); + + JSONObject object = HttpsUtils.doPost("https://api.mch.weixin.qq.com/v3/pay/transactions/h5", param, header); + return ResponseMsgUtil.success(object); + } catch (Exception e) { + log.error("orderToPay error!", e); + return ResponseMsgUtil.exception(e); + } + } + + String getToken(String method, String url, String body) throws UnsupportedEncodingException, SignatureException, NoSuchAlgorithmException, InvalidKeyException, FileNotFoundException { + + long timeMillis = System.currentTimeMillis(); + String nonceStr = String.valueOf(timeMillis); + long timestamp = System.currentTimeMillis() / 1000; + String message = buildMessage(method, url, timestamp, nonceStr, body); + PrivateKey privateKey = PemUtil.loadPrivateKey(new FileInputStream("G:/hurui-project/hai-parent/hai-cweb/src/main/resources/privatekey/apiclient_key.pem")); + String signature = sign(privateKey,message.getBytes("utf-8")); + + return "mchid=\"" + SysConst.getSysConfig().getWxSubMchId() + "\"," + + "nonce_str=\"" + nonceStr + "\"," + + "timestamp=\"" + timestamp + "\"," + + "serial_no=\"" + "1B08DC2A078B0B1F77A65C97C445AAD545B5EAA6" + "\"," + + "signature=\"" + signature + "\""; + } + + String sign(PrivateKey privateKey,byte[] message) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException { + Signature sign = Signature.getInstance("SHA256withRSA"); + sign.initSign(privateKey); + sign.update(message); + return Base64.getEncoder().encodeToString(sign.sign()); + } + + String buildMessage(String method, String url, long timestamp, String nonceStr, String body) { + return method + "\n" + + url + "\n" + + timestamp + "\n" + + nonceStr + "\n" + + body + "\n"; + } } diff --git a/hai-cweb/src/main/resources/dev/config.properties b/hai-cweb/src/main/resources/dev/config.properties index 39e3ba86..21bbf7d7 100644 --- a/hai-cweb/src/main/resources/dev/config.properties +++ b/hai-cweb/src/main/resources/dev/config.properties @@ -9,7 +9,7 @@ wxApiKey=Skufk5oi85wDFGl888i6wsRSTkdd5df5 wxMchAppId=wx637bd6f7314daa46 wxMchId=1289663601 wxSubAppId=wx8d49e2f83025229d -wxSubMchId=1603942866 +wxSubMchId=1609882817 wxUnifiedOrderUrl=https://api.mch.weixin.qq.com/pay/unifiedorder notifyUrl=https://hsgcs.dctpay.com/crest/wechatpay/notify diff --git a/hai-cweb/src/main/resources/privatekey/apiclient_cert.p12 b/hai-cweb/src/main/resources/privatekey/apiclient_cert.p12 new file mode 100644 index 00000000..56614020 Binary files /dev/null and b/hai-cweb/src/main/resources/privatekey/apiclient_cert.p12 differ diff --git a/hai-cweb/src/main/resources/privatekey/apiclient_cert.pem b/hai-cweb/src/main/resources/privatekey/apiclient_cert.pem new file mode 100644 index 00000000..b4bd434b --- /dev/null +++ b/hai-cweb/src/main/resources/privatekey/apiclient_cert.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIUGwjcKgeLCx93plyXxEWq1UW16qYwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT +FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg +Q0EwHhcNMjEwNTMwMTMwNTM1WhcNMjYwNTI5MTMwNTM1WjBvMRMwEQYDVQQDDAox +NjA5ODgyODE3MRswGQYDVQQKDBLlvq7kv6HllYbmiLfns7vnu58xGzAZBgNVBAsM +EuS4quS9k+aIt+m7juadqOePjTELMAkGA1UEBgwCQ04xETAPBgNVBAcMCFNoZW5a +aGVuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvyofjHIn+PWAwM9Z +2/uv8hyRCP+nh8YcylUrRsgQtjoKi1HbRtj9AAwo0eBKgFZ3IviM2+4kQRctcN76 +cGBVGJh8Pvz7MreZgqTLPVHDLz5aVuyc7gzjCQ9o4B5pRjCdR3ORQuK1E+F65IGK +Ez2CjuVnZ+hGvsKhP2NExdhJJbLql3Za9G65Q0fU2z300g01wrRldv3lNr8cXWCr +7AAC491pqpa+yqGzibQustXPG4E3cFew/ZEvI+Said8YchrZmzlImaOS0JFGsSO+ +W0DAemP+k+UfZ8AoipQ4VZvL5MsEjnTk9MvmGiqXr4pS1iqJggWcKgk6g4w+FI5i +INRKkQIDAQABo4GBMH8wCQYDVR0TBAIwADALBgNVHQ8EBAMCBPAwZQYDVR0fBF4w +XDBaoFigVoZUaHR0cDovL2V2Y2EuaXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2Ny +bD9DQT0xQkQ0MjIwRTUwREJDMDRCMDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyMA0G +CSqGSIb3DQEBCwUAA4IBAQCijzFxcaRNdoHzWKMlNNj/WI8j0tqaE6tublseIsZq +fzysnAuadSuawPVyHmPlaOD/wmB+sLkmQECgsgg0dloxETLdElQztSOok6GO+SLm +uRUgDbQJ5wpUu4YphdW2WFpXF2uLgbOvRBJGKiMsTY2FutyTlvj7kqQnhoBr5XWW +08cH40LvHte1/slRpoy0QM0zGZAGGMkNIgKGwlmF5jDuEIyZJs0lrNIJUOoxnZBU +4l7NZhZqckP8bWw0Dyfy4hGw/NAd7gI5nX9yiX185C6aqJr5Aw05HloJHNxMbtTj +5LtFybU6ZAazTWkY301c8CF7tlsaIglnsf/6odkSYn+u +-----END CERTIFICATE----- diff --git a/hai-cweb/src/main/resources/privatekey/apiclient_key.pem b/hai-cweb/src/main/resources/privatekey/apiclient_key.pem new file mode 100644 index 00000000..e1fb0608 --- /dev/null +++ b/hai-cweb/src/main/resources/privatekey/apiclient_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC/Kh+Mcif49YDA +z1nb+6/yHJEI/6eHxhzKVStGyBC2OgqLUdtG2P0ADCjR4EqAVnci+Izb7iRBFy1w +3vpwYFUYmHw+/Psyt5mCpMs9UcMvPlpW7JzuDOMJD2jgHmlGMJ1Hc5FC4rUT4Xrk +gYoTPYKO5Wdn6Ea+wqE/Y0TF2EklsuqXdlr0brlDR9TbPfTSDTXCtGV2/eU2vxxd +YKvsAALj3Wmqlr7KobOJtC6y1c8bgTdwV7D9kS8j5JqJ3xhyGtmbOUiZo5LQkUax +I75bQMB6Y/6T5R9nwCiKlDhVm8vkywSOdOT0y+YaKpevilLWKomCBZwqCTqDjD4U +jmIg1EqRAgMBAAECggEBAIiEOnd/5o/iMwp+iXuR5/qM7/5vJGLP1iugWwF3Sof4 +NyN7V47m0va/uD75X/r6xKXSvjUpgfaB6M+cTVkHUn34F3KcE4AKobQsn3+w7iTE +8Jr26rMNvOzxdkHnNeMMQKWQIIKViB8kfTDGWaaX3K7ToN8Rf8QnFiRAbhKj/MjQ +GSXTcFJ9004jBGB+EawWC9rekZo2mHiEQWVYtDEYBnSJ9fQeg4b6Fo7IN/SMoLSM +HONNsq/uiQJjZr8Tm/5S1Wq1UTw1kiU9CyEG6dnsFkWSfrcrgeEbKHs7DATu0h9p +sVfvu/+fiDq9AoahDvfw1X+Pg4z3gy+PCH3Z3TNnEqkCgYEA9M09FSqvgDdzgtnz +xzF4dppIMxTfSls2Cg1+2Gdgj/P9ffi21LgYzPPIMpSiVGRY3QQiKfCq8Ba9+IWd +azB09z6D+pDjOUcQzGfH0bQsmYDGPNiO5o+oZYf0cr+GZ23NQBwDGZR8xjqjsBEB +XPWPMWOIN8gzoLo6O3VdxRhCUrMCgYEAx+jDoFCDKjvrJhAcUW6cKgXZ0izdLobK +4qDH26Afw2Ju2F/3b8e9+5L8WLqziFydvUQfcLl3btHrzctx2XE4YRRIiufAuEJz +8yBKjCCIGeHRdMtwVx8x+b1NQftTb8k/d5NmYnqZiYQyD3l+1R5Rmk1Zl2FkFut5 +EJCrxE+fP6sCgYBTxaRAiRHzw4YQ4jrtEH3TwGoyqNLcpCfy+rlMntvJh0pZAHK4 +iqNaB5ab0IdYb9qFD7QNPCGS9YVe9YJwOu3b6hXJ+ij34dzaxiz4Ezsr8IhmLAmC +1uhejk7Vsbrxy/5wEOXyrACi6VA4oSkhQZsV4KStyiH4v6HL1RcYqnuPxwKBgQCP +fxqlggWVFGun59qb7Xz1gTuo7YFbO3B5GxY7JYaHVqngcYqI12UdJ5YyDtp+YJTt +3e9/l/IOP2s3TvkLL4Vb0hZ8dvzUhwb6F0zLpzJq+bjDUKD0OLVD4kmJumFbFaeU +Kt9Mg1qg5p6Ukw6i5l+HFkzgKA2TkjVV2bMieFEEfwKBgHAxLffRyMer0vEzs7iq +Sm05FVoURm9wqeM0SCpXtXOtuXiDoxtw8jSCh/mXTiKAgEx3K/KO4fiBB5tCQKzA +TYcP72Jmqvuc4d/5FFH2sKuCiJ5s/XAlGo2zGSDbbkV7KJnRxOtYptW3Zt1VBQG1 +ECOoJd0HryxcP3qSddJHPMV9 +-----END PRIVATE KEY----- diff --git a/hai-service/pom.xml b/hai-service/pom.xml index b4de946e..24ce40c8 100644 --- a/hai-service/pom.xml +++ b/hai-service/pom.xml @@ -298,6 +298,11 @@ 1.1.3 compile + + com.github.wechatpay-apiv3 + wechatpay-apache-httpclient + 0.2.2 + diff --git a/hai-service/src/main/java/com/hai/common/utils/HttpsUtils.java b/hai-service/src/main/java/com/hai/common/utils/HttpsUtils.java index 006feccb..1fbd49c6 100644 --- a/hai-service/src/main/java/com/hai/common/utils/HttpsUtils.java +++ b/hai-service/src/main/java/com/hai/common/utils/HttpsUtils.java @@ -338,6 +338,45 @@ public class HttpsUtils { return null; } + public static JSONObject doWxH5PayPost(String apiUrl, Map body, Map header) { + CloseableHttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + + try { + HttpPost httpPost = new HttpPost(apiUrl); + httpPost.setConfig(requestConfig); + for (Map.Entry entry : header.entrySet()) { + httpPost.setHeader(entry.getKey(), entry.getValue().toString()); + } + StringEntity stringEntity = new StringEntity(body.get("from").toString());// 解决中文乱码问题 + stringEntity.setContentEncoding("UTF-8"); + stringEntity.setContentType("application/x-www-form-urlencoded"); + httpPost.setEntity(stringEntity); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + /** * 发送 POST 请求,JSON形式 *