From 98b094eaa4d28406fc0354c945df353a6645b1a5 Mon Sep 17 00:00:00 2001 From: sjm <1191068887@qq.com> Date: Mon, 10 Jul 2023 17:49:31 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E6=94=AF=E4=BB=98=E9=9B=86?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/ruoyi/RuoYiApplication.java | 3 + .../src/main/resources/application-druid.yml | 5 ++ .../src/main/resources/application.yml | 6 ++ .../resources/wechatpay/apiclient_cert.p12 | Bin 0 -> 2774 bytes .../resources/wechatpay/apiclient_cert.pem | 25 ++++++ .../resources/wechatpay/apiclient_key.pem | 28 +++++++ .../com/fjp/lc/test/service/ServiceTest.java | 18 +++++ ruoyi-mall/pom.xml | 5 ++ .../com/cyl/config/RestTemplateConfig.java | 73 ++++++++++++++++++ .../com/cyl/wechat/WechatAuthService.java | 44 +++++++++++ .../java/com/cyl/wechat/WechatPayConfig.java | 27 +++++++ .../java/com/cyl/wechat/WechatPayData.java | 49 ++++++++++++ .../java/com/cyl/wechat/WechatPayService.java | 41 ++++++++++ .../cyl/wechat/response/WechatUserAuth.java | 13 ++++ 14 files changed, 337 insertions(+) create mode 100644 ruoyi-admin/src/main/resources/wechatpay/apiclient_cert.p12 create mode 100644 ruoyi-admin/src/main/resources/wechatpay/apiclient_cert.pem create mode 100644 ruoyi-admin/src/main/resources/wechatpay/apiclient_key.pem create mode 100644 ruoyi-mall/src/main/java/com/cyl/config/RestTemplateConfig.java create mode 100644 ruoyi-mall/src/main/java/com/cyl/wechat/WechatAuthService.java create mode 100644 ruoyi-mall/src/main/java/com/cyl/wechat/WechatPayConfig.java create mode 100644 ruoyi-mall/src/main/java/com/cyl/wechat/WechatPayData.java create mode 100644 ruoyi-mall/src/main/java/com/cyl/wechat/WechatPayService.java create mode 100644 ruoyi-mall/src/main/java/com/cyl/wechat/response/WechatUserAuth.java diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java index c857bd1..f9692af 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java @@ -1,8 +1,10 @@ package com.ruoyi; +import com.cyl.wechat.WechatPayData; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; /** * 启动程序 @@ -13,6 +15,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; exclude = {DataSourceAutoConfiguration.class}, scanBasePackages = {"com.ruoyi", "com.cyl"} ) +@EnableConfigurationProperties(WechatPayData.class) public class RuoYiApplication { public static void main(String[] args) { // System.setProperty("spring.devtools.restart.enabled", "false"); diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml index 9e41d8a..f3d9e32 100644 --- a/ruoyi-admin/src/main/resources/application-druid.yml +++ b/ruoyi-admin/src/main/resources/application-druid.yml @@ -45,6 +45,11 @@ aliyun: wechat: appId: 你的微信服务号信息 secret: 你的微信服务号信息 + merchantId: + privateKeyPath: + merchantSerialNumber: + apiV3key: + notifyUrl: sms: enabled: true # 阿里云 dysmsapi.aliyuncs.com diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index dbb6af2..9378180 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -161,6 +161,12 @@ extra: redirect: "" scheduling: enabled: true +http-pool: + connection-request-timeout: 10000 + connection-timeout: 10000 + socket-timeout: 10000 + max-per-route: 200 + max-total: 200 gen: # 作者 author: diff --git a/ruoyi-admin/src/main/resources/wechatpay/apiclient_cert.p12 b/ruoyi-admin/src/main/resources/wechatpay/apiclient_cert.p12 new file mode 100644 index 0000000000000000000000000000000000000000..2cc1411825e7bb34e13d92afafd8d5c2ae7cd3d4 GIT binary patch literal 2774 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 R8qr`_P4ANg@#L#N{sn!W5wrjR literal 0 HcmV?d00001 diff --git a/ruoyi-admin/src/main/resources/wechatpay/apiclient_cert.pem b/ruoyi-admin/src/main/resources/wechatpay/apiclient_cert.pem new file mode 100644 index 0000000..e5d21be --- /dev/null +++ b/ruoyi-admin/src/main/resources/wechatpay/apiclient_cert.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEKzCCAxOgAwIBAgIUW0mbrKuZqAqNv3ZTP/ylJOrmuIAwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT +FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg +Q0EwHhcNMjMwNzEwMDMwMDA2WhcNMjgwNzA4MDMwMDA2WjCBhDETMBEGA1UEAwwK +MTY0MDE2NTIyOTEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMTAwLgYDVQQL +DCfoi4/lt57or5rkuI7kuZDkv6Hmga/mioDmnK/mnInpmZDlhazlj7gxCzAJBgNV +BAYMAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBALrELkqmSy8PkSk3KL3eNwQKm08xvIsrk3KKuyS7YrulQaKmqfvn +Nh0qXfgFYCqOKlV6VBEAxSRfsNq1/NsVCa5ZGcrcHlf0iC22p81w0W0TTT4LzfRj +tuobO/uhLhtHHaWxyVdloRirHEl5xXREvI6xstjEEG5vYyIFxR2Aufpv6e20FpZ3 +G3KiTSRFoSSHMJjOoPEeGd6nAzueqGGjdGcxNHl/a9HDyYcRMeIO9k1Wd1gcwwpu +vinELhB1ojpzO6UekAzjM4g7QD2aAibmb0/Q+4hFw7xXOrOElt0hjKcoG+hZGlFL +xjLCC+Z/xbLEz1jtH7mAdUG/g2Ls4pr470UCAwEAAaOBuTCBtjAJBgNVHRMEAjAA +MAsGA1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGEaHR0cDovL2V2 +Y2EuaXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJD +MDRCMDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFCNjU0MjJFMTJC +MjdBOUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEBCwUAA4IBAQBK +udnDDPqczbrX8RmKcw5rixMyM5toyMtqNR1pfkWCG2QP2PmNTYBARO2tW2DZtWZm +eLuUXZVE12FnIkEQQ65JmDEEvz8PwTSQIPCcObHUGKuj5dFWswzYEWMsqIdPfGK+ +Teb294FsTRiElDMkpt3pmYkGVxFwsAfSFZM/9Gl45HdagD4RHfvRDgB8WGx6azxX +w/kn8CHJqLEJtbPer8cGFCih0v0LfLCy4MEHb0Si0PWoEmecTE3DtXK5gEKLFlEy +g1Gb16LW1eEGwyfqcUmwXDE3aamL4RpxjZgzIagvsqVfPn7nDiw6fFf78Ya0ClVx +ImJDoCe+5aH652BNZXWD +-----END CERTIFICATE----- diff --git a/ruoyi-admin/src/main/resources/wechatpay/apiclient_key.pem b/ruoyi-admin/src/main/resources/wechatpay/apiclient_key.pem new file mode 100644 index 0000000..e6953ab --- /dev/null +++ b/ruoyi-admin/src/main/resources/wechatpay/apiclient_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6xC5KpksvD5Ep +Nyi93jcECptPMbyLK5Nyirsku2K7pUGipqn75zYdKl34BWAqjipVelQRAMUkX7Da +tfzbFQmuWRnK3B5X9IgttqfNcNFtE00+C830Y7bqGzv7oS4bRx2lsclXZaEYqxxJ +ecV0RLyOsbLYxBBub2MiBcUdgLn6b+nttBaWdxtyok0kRaEkhzCYzqDxHhnepwM7 +nqhho3RnMTR5f2vRw8mHETHiDvZNVndYHMMKbr4pxC4QdaI6czulHpAM4zOIO0A9 +mgIm5m9P0PuIRcO8VzqzhJbdIYynKBvoWRpRS8Yywgvmf8WyxM9Y7R+5gHVBv4Ni +7OKa+O9FAgMBAAECggEAKlMzOm+dMjkQ6Io7jWvChAPzVmsrE074x0hxSM2+fk/h +I/8pHpEzTkC/sulk9b/qEBz82C2Yf7m/1pDPkMafvwcqNTLVHZGpGtL+DCy5CUMK +ijkan3vJhBxP56KLVFs1eMtlmYzKiVCdxHj4KnU5Vg0nPsCQCLbtfFRaa2k0vHAl +LpaC+HG/nFMewTC9NBcfu+IMzs5miUgvWpkAVXvq4WcJq+ACsnc2rzDlEa7ZNaNR +3CtHCj+f7Yhnt+U+IImIGLeh2Z1wR7dCxnuAQ02W0pWl8pIUmrL8m9LwRrgL1Rje +Fp1DXTXKlCl3oHELz9qHfJ06K2r5laCqMV2s6esTgQKBgQDfNnev21ydMe7F6NaO +0s1Xb4Btl9NSiCEoTjdt/w2rCFdvu0YsgutaB0J4rk2Jeyp7MlHiYkUn1X/dJlMX +/P/hmgtnnFJotIvHFl3nHem8l10mB+MYCeI65uDOvEcXoGV+jMTZd4wzJlSC/uio +UbsWf7ykHMW8M77fbzncY5MOiQKBgQDWMzU0NfRdVE3Y7c7vfJr2jMPhkB5ai5Cr +PK+kCbVKALR79C4aPaUM3RmYaG61NPaylw1+czv1YxWvtiHidiGAM3t/18qbKicf +SQxqe4uFAXWMafopThPLw9KGq0sSjOs9DDt8CIscAzAs9ykj2DT2khfAeqZdwjDo +CVnWKtmL3QKBgQDRYMNGd2tZnPQQO0e/82dgpBwBMVCt8zm/GBeQm5YToCB8k1vQ +9wGTkom8sCvVUW5Y36vFwk6CfheRt5hsQQs5cQlPqGf5BZq0JnvxBrMxD3715KIV +83d9rwKjiiLZu8BYw+0G3MfrVwIhWsGc2gW3phyqiL7GundKGYhZ/iF8mQKBgATd +BMg6sWGtGFdkjt5BJgOTDp+Adi/4G0DID/TZg5Q6j96AnMtbuvOf0YT0Wg8jNLa5 +V0UXuLTJmyRyLjLGG9ydTqCIdcEwI9NCBVYll/VdIx4dCeEGNMzblVwZZ4r0SCMK +tA8M4puwNtfOhNCbiBhRGNj17/ERB6s9Cx0hu+7BAoGAV3nfA3JACh30oStpZQab +CY3JJvqIFINGk1h8cY9yjlI/g6WXw6ACtIVhvy9bEOkSFgtMdCFWVLC/E836p2Qo +38J4DLiXszt+4y8PFviVszVFZIRkHOOluRXSedDmPteu4bQCCXO4MCzC502PKcyM +X38MmpqzqQxZoe5PbwJENR0= +-----END PRIVATE KEY----- diff --git a/ruoyi-admin/src/test/java/com/fjp/lc/test/service/ServiceTest.java b/ruoyi-admin/src/test/java/com/fjp/lc/test/service/ServiceTest.java index 6562ff6..e0ad6c7 100644 --- a/ruoyi-admin/src/test/java/com/fjp/lc/test/service/ServiceTest.java +++ b/ruoyi-admin/src/test/java/com/fjp/lc/test/service/ServiceTest.java @@ -6,6 +6,9 @@ import cn.hutool.core.util.IdUtil; import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.symmetric.AES; import com.cyl.manager.ums.service.MemberCartService; +import com.cyl.wechat.WechatAuthService; +import com.cyl.wechat.WechatPayService; +import com.cyl.wechat.response.WechatUserAuth; import com.ruoyi.RuoYiApplication; import com.ruoyi.common.config.properties.SmsProperties; import com.ruoyi.common.core.sms.AliyunSmsTemplate; @@ -21,6 +24,7 @@ import org.springframework.test.context.junit4.SpringRunner; import java.util.HashMap; import java.util.Map; +import java.util.UUID; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = RuoYiApplication.class) @@ -73,4 +77,18 @@ public class ServiceTest { long id = snowflake.nextId(); System.out.println("id:" + id); } + + @Autowired + private WechatPayService wechatPayService; + @Autowired + private WechatAuthService wechatAuthService; + @Test + public void test5(){ +// String code = "0611P2Ga1D8QCF0CVuJa1qNUJa11P2GL"; +// WechatUserAuth userToken = wechatAuthService.getUserToken(code); + String openId="oUA8I6lDdwSfz-EwR4284dU3KOYw"; + String res = wechatPayService.jsapiPay(UUID.randomUUID().toString().substring(0,30), "测试支付", 1, openId); + System.out.println(res); + + } } diff --git a/ruoyi-mall/pom.xml b/ruoyi-mall/pom.xml index 08a3b55..30f6a37 100644 --- a/ruoyi-mall/pom.xml +++ b/ruoyi-mall/pom.xml @@ -23,6 +23,11 @@ ruoyi-system ${ruoyi.version} + + com.github.wechatpay-apiv3 + wechatpay-java + 0.2.9 + com.baomidou mybatis-plus-boot-starter diff --git a/ruoyi-mall/src/main/java/com/cyl/config/RestTemplateConfig.java b/ruoyi-mall/src/main/java/com/cyl/config/RestTemplateConfig.java new file mode 100644 index 0000000..1788a6d --- /dev/null +++ b/ruoyi-mall/src/main/java/com/cyl/config/RestTemplateConfig.java @@ -0,0 +1,73 @@ +package com.cyl.config; + + +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfig { + //从连接池获取连接的超时时间,一般设置为较短; + @Value("${http-pool.connection-request-timeout}") + private int connectionRequestTimeout; + + //连接超时时间 + @Value("${http-pool.connection-timeout}") + private int connectionTimeout; + + //完成连接后,socket通信超时时间 + @Value("${http-pool.socket-timeout}") + private int socketTimeout; + + //单host(可以理解为单域名)最大并发数 + @Value("${http-pool.max-per-route}") + private int maxPerRoute; + + //连接池最大连接数 + @Value("${http-pool.max-total}") + private int maxTotal; + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(httpRequestFactory()); + } + + @Bean + public ClientHttpRequestFactory httpRequestFactory() { + return new HttpComponentsClientHttpRequestFactory(httpClient()); + } + + @Bean + public HttpClient httpClient() { + Registry registry = RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .build(); + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry); + //设置整个连接池最大连接数 根据自己的场景决定 + connectionManager.setMaxTotal(maxTotal); + //路由是对maxTotal的细分 + connectionManager.setDefaultMaxPerRoute(maxPerRoute); + RequestConfig requestConfig = RequestConfig.custom() + .setSocketTimeout(socketTimeout)//服务器返回数据(response)的时间,超过该时间抛出read timeout + .setConnectTimeout(connectionTimeout)//连接上服务器(握手成功)的时间,超出该时间抛出connect timeout + .setConnectionRequestTimeout(connectionRequestTimeout)//从连接池中获取连接的超时时间,超过该时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool + .build(); + return HttpClientBuilder.create() + .setDefaultRequestConfig(requestConfig) + .setConnectionManager(connectionManager) + .build(); + } +} diff --git a/ruoyi-mall/src/main/java/com/cyl/wechat/WechatAuthService.java b/ruoyi-mall/src/main/java/com/cyl/wechat/WechatAuthService.java new file mode 100644 index 0000000..1b9de51 --- /dev/null +++ b/ruoyi-mall/src/main/java/com/cyl/wechat/WechatAuthService.java @@ -0,0 +1,44 @@ +package com.cyl.wechat; + +import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson.JSON; +import com.cyl.wechat.response.WechatUserAuth; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.util.HashMap; +import java.util.Map; + +@Service +@Slf4j +public class WechatAuthService { + + @Autowired + private RestTemplate restTemplate; + + public WechatUserAuth getUserToken(String code) { + Map params = new HashMap<>(); + params.put("APPID", WechatPayData.appId); + params.put("SECRET", WechatPayData.secret); + params.put("CODE", code); + ResponseEntity responseEntity = restTemplate.getForEntity( + "https://api.weixin.qq.com/sns/oauth2/access_token?appid={APPID}&secret={SECRET}&code={CODE}&grant_type=authorization_code", + String.class, params); + String body = responseEntity.getBody(); + try { + WechatUserAuth object = JSON.parseObject(body, WechatUserAuth.class); + if (object == null) { + log.error("获取user wechat accesstoken失败"); + return null; + } + log.info("get user wechat accesstoken:{}",JSONUtil.toJsonStr(object)); + return object; + } catch (Exception e) { + log.info("get user wechat accesstoken error",e); + } + return null; + } +} diff --git a/ruoyi-mall/src/main/java/com/cyl/wechat/WechatPayConfig.java b/ruoyi-mall/src/main/java/com/cyl/wechat/WechatPayConfig.java new file mode 100644 index 0000000..6cd53ef --- /dev/null +++ b/ruoyi-mall/src/main/java/com/cyl/wechat/WechatPayConfig.java @@ -0,0 +1,27 @@ +package com.cyl.wechat; + +import com.wechat.pay.java.core.Config; +import com.wechat.pay.java.core.RSAAutoCertificateConfig; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; + +public class WechatPayConfig { + + private static Config wechatPayConfig; + + private WechatPayConfig(){} + + public static Config getInstance() { + + + if (wechatPayConfig == null) { + wechatPayConfig = new RSAAutoCertificateConfig.Builder() + .merchantId(WechatPayData.merchantId) + .privateKeyFromPath(WechatPayConfig.class.getResource(WechatPayData.privateKeyPath).getPath()) + .merchantSerialNumber(WechatPayData.merchantSerialNumber) + .apiV3Key(WechatPayData.apiV3key) + .build(); + } + return wechatPayConfig; + } +} diff --git a/ruoyi-mall/src/main/java/com/cyl/wechat/WechatPayData.java b/ruoyi-mall/src/main/java/com/cyl/wechat/WechatPayData.java new file mode 100644 index 0000000..f4dc49d --- /dev/null +++ b/ruoyi-mall/src/main/java/com/cyl/wechat/WechatPayData.java @@ -0,0 +1,49 @@ +package com.cyl.wechat; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties(prefix = "wechat") +public class WechatPayData { + + /** 商户号 */ + public static String appId; + public static String secret; + public static String merchantId; + /** 商户API私钥路径 */ + public static String privateKeyPath; + /** 商户证书序列号 */ + public static String merchantSerialNumber; + /** 商户APIV3密钥 */ + public static String apiV3key; + public static String notifyUrl; + + public void setAppId(String appId) { + WechatPayData.appId = appId; + } + + public void setSecret(String secret) { + WechatPayData.secret = secret; + } + + public void setMerchantId(String merchantId) { + WechatPayData.merchantId = merchantId; + } + + public void setPrivateKeyPath(String privateKeyPath) { + WechatPayData.privateKeyPath = privateKeyPath; + } + + public void setMerchantSerialNumber(String merchantSerialNumber) { + WechatPayData.merchantSerialNumber = merchantSerialNumber; + } + + public void setApiV3key(String apiV3key) { + WechatPayData.apiV3key = apiV3key; + } + + public void setNotifyUrl(String notifyUrl) { + WechatPayData.notifyUrl = notifyUrl; + } +} diff --git a/ruoyi-mall/src/main/java/com/cyl/wechat/WechatPayService.java b/ruoyi-mall/src/main/java/com/cyl/wechat/WechatPayService.java new file mode 100644 index 0000000..9d062c8 --- /dev/null +++ b/ruoyi-mall/src/main/java/com/cyl/wechat/WechatPayService.java @@ -0,0 +1,41 @@ +package com.cyl.wechat; + +import com.wechat.pay.java.service.payments.jsapi.JsapiService; +import com.wechat.pay.java.service.payments.jsapi.model.Amount; +import com.wechat.pay.java.service.payments.jsapi.model.Payer; +import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest; +import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class WechatPayService { + + public static final JsapiService service = new JsapiService.Builder().config(WechatPayConfig.getInstance()).build(); + + /** + * jsapi下单 + * @param orderNo 订单号 + * @param desc 订单描述 + * @param totalAmount 总金额,单位:分 + * @param openId 用户openid + * @return prepay_id + */ + public String jsapiPay(String orderNo,String desc,Integer totalAmount,String openId){ + PrepayRequest prepayRequest = new PrepayRequest(); + prepayRequest.setAppid(WechatPayData.appId); + prepayRequest.setMchid(WechatPayData.merchantId); + prepayRequest.setDescription(desc); + prepayRequest.setOutTradeNo(orderNo); + prepayRequest.setNotifyUrl(WechatPayData.notifyUrl); + Amount amount = new Amount(); + amount.setTotal(totalAmount); + prepayRequest.setAmount(amount); + Payer payer = new Payer(); + payer.setOpenid(openId); + prepayRequest.setPayer(payer); + PrepayResponse response = service.prepay(prepayRequest); + return response.getPrepayId(); + } +} diff --git a/ruoyi-mall/src/main/java/com/cyl/wechat/response/WechatUserAuth.java b/ruoyi-mall/src/main/java/com/cyl/wechat/response/WechatUserAuth.java new file mode 100644 index 0000000..b659482 --- /dev/null +++ b/ruoyi-mall/src/main/java/com/cyl/wechat/response/WechatUserAuth.java @@ -0,0 +1,13 @@ +package com.cyl.wechat.response; + +import lombok.Data; + +@Data +public class WechatUserAuth { + + private String access_token; + private Integer expires_in; + private String refresh_token; + private String openid; + private String scope; +} \ No newline at end of file