更新時(shí)間:2023-09-01 來(lái)源:黑馬程序員 瀏覽量:
基于啟動(dòng)類上的注解@SpringBootApplication中的@EnableAutoConfiguration來(lái)開啟自動(dòng)化配置,這個(gè)注解通過(guò)@Import來(lái)導(dǎo)入了配置類,如下圖所示:
上述配置類會(huì)加載所有jar包以及源碼下的META-INF下得spring.factories文件,如下圖所示:
然后會(huì)加載配置中指定的自動(dòng)化配置key所對(duì)應(yīng)的所有自動(dòng)化配置類,示例如下圖所示:
但是自動(dòng)化配置類并不是都需要加載的,springBoot通過(guò)自動(dòng)化配置類上添加的各種條件注解@Conditional來(lái)判斷這個(gè)自動(dòng)化配置類是否滿足條件,如果滿足條件,即加載配置類,如下圖webmvc自動(dòng)化配置類示例:
微信掃碼支付starter封裝
流程分析--逆向思維
我們最終需要能夠?qū)崿F(xiàn)的目的 -->引入依賴,yaml中做好配置,直接依賴注入xxxTemplate能夠直接使用。
--->需要?jiǎng)?chuàng)建一個(gè)xxxTemplate對(duì)象---> 提供一個(gè)xxxTemplate類,封裝掃碼支付的api,一些環(huán)境級(jí)別的參數(shù)做成配置。
--> 提供xxxProperties配置類,然后加載yaml中的配置。
實(shí)現(xiàn)步驟整理
01.創(chuàng)建工程,引入相關(guān)依賴
提供WxPayProperties配置類,用于加載application.yaml中的環(huán)境配置
提供WxPayTemplate類,封裝掃碼支付的api,環(huán)境配置依賴注入得到
提供配置類,啟動(dòng)WxPayProperties類對(duì)象,創(chuàng)建WxPayTemplate對(duì)象
提供META-INF/spring.factory配置類,配置自動(dòng)化配置
創(chuàng)建新測(cè)試工程,測(cè)試starter使用
代碼實(shí)現(xiàn)
1.創(chuàng)建工程,引入相關(guān)依賴
<dependencies> <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-apache-httpclient</artifactId> <version>0.4.9</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> </dependencies>
提供WxPayProperties配置類,用于加載application.yaml中的環(huán)境配置
package com.heima.wxpay.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Data @ConfigurationProperties(prefix = "wxpay") public class WxPayProperties { private String mchId = "1561414331"; //商戶號(hào) //private String appId = "wx6592a2db3f85ed25"; //應(yīng)用號(hào) private String appId = "wxffb3637a228223b8"; //應(yīng)用號(hào) private String privateKey = "-----BEGIN PRIVATE KEY-----\n" + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDBHGgIh80193Gh\n" + "dpD1LtMZfTRpcWI0fImyuBCyrd3gYb3rrsARebGcHdJsQA3mVjVqVp5ybhEZDPa4\n" + "ecoK4Ye1hTppNpI/lmLt4/uUV/zhF5ahli7hi+116Ty6svHSbuMQBuUZeTFOwGrx\n" + "jvofU/4pGIwh8ZvkcSnyOp9uX2177UVxDBkhgbZbJp9XF2b83vUa5eHo93CziPzn\n" + "3hFdAlBCdTXB7DH+m0nN3Jou0szGukvq7cIgGpHku4ycKSTkIhhl9WRhN6OoSEJx\n" + "q88MXzjkzTruc85PHN52aUTUifwg3T8Y4XqFQ61dTnEmgxeD2O6/pLdB9gLsp6yC\n" + "GqN5Lqk7AgMBAAECggEBAL4X+WzUSbSjFS9NKNrCMjm4H1zgqTxjj6TnPkC1mGEl\n" + "tjAHwLgzJBw62wWGdGhWWpSIGccpBBm1wjTMZpAZfF66fEpP1t1Ta6UjtGZNyvfF\n" + "IZmE3jdWZ/WXGBnsxtFQKKKBNwrBW0Fbdqq9BQjLxLitmlxbmwrgPttcy855j6vZ\n" + "qq4MBT1v8CtUT/gz4UWW2xWovVnmWOrRSScv7Nh0pMbRpPLkNHXrBwSSNz/keORz\n" + "XB9JSm85wlkafa7n5/IJbdTml3A/uAgW3q3JZZQotHxQsYvD4Zb5Cnc9CPAXE5L2\n" + "Yk877kVXZMGt5QPIVcPMj/72AMtaJT67Y0fN0RYHEGkCgYEA38BIGDY6pePgPbxB\n" + "7N/l6Df0/OKPP0u8mqR4Q0aQD3VxeGiZUN1uWXEFKsKwlOxLfIFIFk1/6zQeC0xe\n" + "tNTKk0gTL8hpMUTNkE7vI9gFWws2LY6DE86Lm0bdFEIwh6d7Fr7zZtyQKPzMsesC\n" + "3XV9sdSUExEi5o/VwAyf+xZlOXcCgYEA3PGZYlILjg3esPNkhDz2wxFw432i8l/B\n" + "CPD8ZtqIV9eguu4fVtFYcUVfawBb0T11RamJkc4eiSOqayC+2ehgb+GyRLJNK4Fq\n" + "bFcsIT+CK0HlscZw51jrMR0MxTc4RzuOIMoYDeZqeGB6/YnNyG4pw2sD8bIwHm84\n" + "06gtJsX/v10CgYAo8g3/aEUZQHcztPS3fU2cTkkl0ev24Ew2XGypmwsX2R0XtMSB\n" + "uNPNyFHyvkgEKK2zrhDcC/ihuRraZHJcUyhzBViFgP5HBtk7VEaM36YzP/z9Hzw7\n" + "bqu7kZ85atdoq6xpwC3Yn/o9le17jY8rqamD1mv2hUdGvAGYsHbCQxnpBwKBgHTk\n" + "eaMUBzr7yZLS4p435tHje1dQVBJpaKaDYPZFrhbTZR0g+IGlNmaPLmFdCjbUjiPy\n" + "A2+Znnwt227cHz0IfWUUAo3ny3419QkmwZlBkWuzbIO2mms7lwsf9G6uvV6qepKM\n" + "eVd5TWEsokVbT/03k27pQmfwPxcK/wS0GFdIL/udAoGAOYdDqY5/aadWCyhzTGI6\n" + "qXPLvC+fsJBPhK2RXyc+jYV0KmrEv4ewxlK5NksuFsNkyB7wlI1oMCa/xB3T/2vT\n" + "BALgGFPi8BJqceUjtnTYtI4R2JIVEl08RtEJwyU5JZ2rvWcilsotVZYwfuLZ9Kfd\n" + "hkTrgNxlp/KKkr+UuKce4Vs=\n" + "-----END PRIVATE KEY-----\n"; //私鑰字符串 private String mchSerialNo = "25FBDE3EFD31B03A4377EB9A4A47C517969E6620"; //商戶證書序列號(hào) private String apiV3Key = "CZBK51236435wxpay435434323FFDuv3"; //V3密鑰 }
提供WxPayTemplate類,封裝掃碼支付的api,環(huán)境配置依賴注入得到。
2個(gè)參數(shù)實(shí)體類:
package com.heima.wxpay.dto; import lombok.Builder; import lombok.Data; @Builder @Data public class NativePayParams { private String appid; // 應(yīng)用id private String mchid; // 商戶id private String description; //商品描述 private String out_trade_no; //訂單號(hào) private String notify_url; // 支付成功回調(diào)通知地址 private Amount amount; //訂單金額信息 }
package com.heima.wxpay.dto; import lombok.Builder; import lombok.Data; @Builder @Data public class Amount { private Integer total; private String currency; }
工具類:
package com.heima.wxpay.config; import com.alibaba.fastjson.JSON; import com.heima.wxpay.dto.Amount; import com.heima.wxpay.dto.NativePayParams; 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 java.io.IOException; import java.util.Map; public class WxPayTemplate { private WxPayProperties wxPayProperties; private CloseableHttpClient httpClient; public WxPayTemplate(WxPayProperties wxPayProperties,CloseableHttpClient httpClient) { this.wxPayProperties = wxPayProperties; this.httpClient = httpClient; } public String nativePay(Integer total, String description, String outTradeNo) throws Exception{ HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native"); // 請(qǐng)求body參數(shù) Amount amount = Amount.builder().currency("CNY").total(total).build(); NativePayParams nativePayParams = NativePayParams.builder().appid(wxPayProperties.getAppId()) .description(description) .mchid(wxPayProperties.getMchId()) .notify_url("https://36d5634033.vicp.fun/native/notify") .out_trade_no(outTradeNo) .amount(amount) .build(); String reqdata = JSON.toJSONString(nativePayParams); StringEntity entity = new StringEntity(reqdata,"utf-8"); entity.setContentType("application/json"); httpPost.setEntity(entity); httpPost.setHeader("Accept", "application/json"); //完成簽名并執(zhí)行請(qǐng)求 CloseableHttpResponse response = httpClient.execute(httpPost); String url = ""; try { int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == 200) { //處理成功 System.out.println("success,return body = " + EntityUtils.toString(response.getEntity())); url = JSON.parseObject( EntityUtils.toString(response.getEntity()), Map.class).get("code_url").toString(); } else if (statusCode == 204) { //處理成功,無(wú)返回Body System.out.println("success"); } else { System.out.println("failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity())); throw new IOException("request failed"); } } finally { response.close(); } return url; } }
提供配置類,啟動(dòng)WxPayProperties類對(duì)象,創(chuàng)建WxPayTemplate對(duì)象。
package com.heima.wxpay.config; 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 org.apache.http.impl.client.CloseableHttpClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.io.ByteArrayInputStream; import java.security.PrivateKey; @Configuration @EnableConfigurationProperties(WxPayProperties.class) public class WxPayAutoConfig { @Bean public CloseableHttpClient httpClient(WxPayProperties wxPayProperties) throws Exception{ // 加載商戶私鑰(privateKey:私鑰字符串) PrivateKey merchantPrivateKey = PemUtil .loadPrivateKey(new ByteArrayInputStream(wxPayProperties.getPrivateKey().getBytes("utf-8"))); // 加載平臺(tái)證書(mchId:商戶號(hào),mchSerialNo:商戶證書序列號(hào),apiV3Key:V3密鑰) AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier( new WechatPay2Credentials(wxPayProperties.getMchId(), new PrivateKeySigner(wxPayProperties.getMchSerialNo(), merchantPrivateKey)),wxPayProperties.getApiV3Key().getBytes("utf-8")); // 初始化httpClient return WechatPayHttpClientBuilder.create() .withMerchant(wxPayProperties.getMchId(), wxPayProperties.getMchSerialNo(), merchantPrivateKey) .withValidator(new WechatPay2Validator(verifier)).build(); } @Bean public WxPayTemplate wxPayTemplate(WxPayProperties wxPayProperties,CloseableHttpClient httpClient){ return new WxPayTemplate(wxPayProperties,httpClient); } }
提供META-INF/spring.factory配置類,配置自動(dòng)化配置
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.heima.wxpay.config.WxPayAutoConfig
創(chuàng)建新測(cè)試工程,測(cè)試starter使用,導(dǎo)入starter依賴:
<dependency> <groupId>com.heima</groupId> <artifactId>wx_pay_starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
直接springBoot測(cè)試
package com.itheima.wxpay; import com.heima.wxpay.config.WxPayTemplate; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class StarterTest { @Autowired private WxPayTemplate wxPayTemplate; @Test public void testNativePay() throws Exception{ String url = wxPayTemplate.nativePay(1, "javaEE企業(yè)級(jí)開發(fā)", "ADFADSFS4353534"); System.out.println(url); }