springboot集成 生成二维码微信支付

目录

1、添加依赖

 2、封装工具类

2.1 HttpUtil

2.2 WebServletUtil

2.3 Swagger2Conf

2.4 向微信发送请求并获取code_url

3、控制层

4、配置文件

payconfig.properties

5、测试

5.1、访问doc.html

5.2、获取二维码


1、添加依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.11.0</version>
        </dependency>
          <!--日期序列化-->
        <dependency>
          <groupId>com.fasterxml.jackson.datatype</groupId>
          <artifactId>jackson-datatype-jsr310</artifactId>
          <version>2.9.3</version>
        </dependency>
        <!--自动生成get set 构造方法所需的依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <!--微信支付-->
        <!-- 生成二维码工具 -->
        <dependency>
             <groupId>com.google.zxing</groupId>
             <artifactId>core</artifactId>
             <version>3.2.1</version>
         </dependency>
         <dependency>
             <groupId>com.google.zxing</groupId>
             <artifactId>javase</artifactId>
             <version>3.2.0</version>
         </dependency>
         <!-- 微信支付所需sdk -->
         <dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>

         <!--实现http请求的依赖包-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>

         <!--swagger依赖-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.6</version>
        </dependency>
        <dependency>
            <groupId>com.spring4all</groupId>
            <artifactId>swagger-spring-boot-starter</artifactId>
            <version>1.9.1.RELEASE</version>
        </dependency>

 2、封装工具类

2.1 HttpUtil

public class HttpUtil {
	 private String url;
    private Map<String, String> param;
    private int statusCode;//状态码
    private String content;//主体部分
    private String xmlParam;//生成的xml
    private boolean isHttps;

    public boolean isHttps() {
        return isHttps;
    }

    public void setHttps(boolean isHttps) {
        this.isHttps = isHttps;
    }

    public String getXmlParam() {
        return xmlParam;
    }

    public void setXmlParam(String xmlParam) {
        this.xmlParam = xmlParam;
    }

    public HttpUtil(String url, Map<String, String> param) {
        this.url = url;
        this.param = param;
    }

    public HttpUtil(String url) {
        this.url = url;
    }

    public void setParameter(Map<String, String> map) {
        param = map;
    }

    public void addParameter(String key, String value) {
        if (param == null)
            param = new HashMap<String, String>();
        param.put(key, value);
    }

    public void post() throws ClientProtocolException, IOException {
        HttpPost http = new HttpPost(url);
        setEntity(http);
        execute(http);
    }

    public void put() throws ClientProtocolException, IOException {
        HttpPut http = new HttpPut(url);
        setEntity(http);
        execute(http);
    }

    public void get() throws ClientProtocolException, IOException {
        if (param != null) {
            StringBuilder url = new StringBuilder(this.url);
            boolean isFirst = true;
            for (String key : param.keySet()) {
                if (isFirst)
                    url.append("?");
                else
                    url.append("&");
                url.append(key).append("=").append(param.get(key));
            }
            this.url = url.toString();
        }
        HttpGet http = new HttpGet(url);
        execute(http);
    }

    /**
     * set http post,put param
     */
    private void setEntity(HttpEntityEnclosingRequestBase http) {
        if (param != null) {
            List<NameValuePair> nvps = new LinkedList<NameValuePair>();
            for (String key : param.keySet())
                nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数
            http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数
        }
        if (xmlParam != null) {
            http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));
        }
    }

    private void execute(HttpUriRequest http) throws ClientProtocolException,
            IOException {
        CloseableHttpClient httpClient = null;
        try {
            if (isHttps) {
                SSLContext sslContext = new SSLContextBuilder()
                        .loadTrustMaterial(null, new TrustStrategy() {
                            // 信任所有
                            public boolean isTrusted(X509Certificate[] chain,
                                                     String authType)
                                    throws CertificateException {
                                return true;
                            }
                        }).build();
                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                        sslContext);
                httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
                        .build();
            } else {
                httpClient = HttpClients.createDefault();
            }
            CloseableHttpResponse response = httpClient.execute(http);
            try {
                if (response != null) {
                    if (response.getStatusLine() != null)
                        statusCode = response.getStatusLine().getStatusCode();
                    HttpEntity entity = response.getEntity();
                    // 响应内容
                    content = EntityUtils.toString(entity, Consts.UTF_8);
                }
            } finally {
                response.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            httpClient.close();
        }
    }

    public int getStatusCode() {
        return statusCode;
    }

    public String getContent() throws ParseException, IOException {
        return content;
    }
}

2.2 WebServletUtil

可以根据上下文获取Reques和Response对象

public class WebServletUtil {
	private static ServletRequestAttributes servletRequestAttributes;

	static {
		servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
	}

	public static HttpServletRequest getRequest(){
		return servletRequestAttributes.getRequest();
	}

	public static HttpServletResponse getResponse(){
		return servletRequestAttributes.getResponse();
	}
}

2.3 Swagger2Conf

为了更方便测试接口集成了swagger文档

@Configuration
@EnableSwagger2//开启swagger
public class Swagger2Conf {

    @Bean
    public Docket webApiConfig(){

        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("webApi")
                .apiInfo(webApiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.gzh.weixinpay.controller"))
                //过滤掉所有error或error.*页面
                .paths(Predicates.not(PathSelectors.regex("/error.*")))
                .build();
    }
    private ApiInfo webApiInfo(){

        return new ApiInfoBuilder()
                .title("权限管理API文档")
                .description("本文档描述了权限管理接口定义")
                .version("1.0")
                .contact(new Contact("gzh", "http://taobao.com", "1984274233@qq.com"))
                .build();
    }
}

2.4 向微信发送请求并获取code_url

package com.gzh.weixinpay.conf;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.gzh.weixinpay.util.HttpUtil;
import com.gzh.weixinpay.util.WebServletUtil;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import java.io.OutputStream;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * TODO
 *
 * @author DELL
 * @version 1.0
 * @since 2022-08-12  21:00:56
 */
@Data
@Component("config")
@ConfigurationProperties(prefix = "weixin")//让配置参数能分离出来
@PropertySource("classpath:payconfig.properties")
public class WxConfig implements Serializable {

	@Value("${APPID}")
	private String APPID;

	@Value("${MCH_ID}")
	private String MCH_ID;

	@Value("${KEY}")
	private String KEY;

	@Value("${SPBILL_CREATE_IP}")
	private String SPBILL_CREATE_IP;

	@Value("${NOTIFY_URL}")
	private String NOTIFY_URL;

	@Value("${TRADE_TYPE}")
	private String TRADE_TYPE;

	@Value("${PLACEANORDER_URL}")
	private String PAY_URL;

	@Value("${QUERY_URL}")
	private String QRY_URL;

    /**
     *
     * @param out_trade_no 订单编号
     * @param total_fee   总金额
     * @param expireTimeMin  失效时间
     * @return
     */
    public Map createNative(String out_trade_no, int total_fee , Integer expireTimeMin) throws JsonProcessingException {
        Map<String, String> param = new HashMap();
        param.put("appid", APPID);
        param.put("mch_id", MCH_ID);
        param.put("nonce_str", WXPayUtil.generateNonceStr());
        param.put("body", "测试支付功能"); //定义订单内容
        param.put("out_trade_no", out_trade_no);  //商户订单编号
        param.put("fee_type", "CNY");
        param.put("total_fee", new ObjectMapper().writeValueAsString(total_fee));  //总金额
        param.put("spbill_create_ip", SPBILL_CREATE_IP);
        param.put("notify_url", NOTIFY_URL); //回调地址
        param.put("trade_type", "NATIVE");
        Date date = new Date();
        long time = date.getTime();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String timeStart = simpleDateFormat.format(time);
        String timeEnd = simpleDateFormat.format(time + expireTimeMin * 60000);
        param.put("time_start", timeStart); //订单创建时间
        param.put("time_expire", timeEnd); //定义失效时间
        try {


            String xmlParam = WXPayUtil.generateSignedXml(param, KEY); //参数转换
            HttpUtil client = new HttpUtil(PAY_URL);
            client.setHttps(true);
            client.setXmlParam(xmlParam);
            client.post();
            String result = client.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(result);

            if (resultMap.get("err_code") != null && resultMap.get("err_code").equals("ORDERPAID")) {
                System.out.println("<--"+out_trade_no+"--> :订单已经支付!");

            }

            Map<String, String> map = new HashMap<>();
            String code_url = resultMap.get("code_url");

            map.put("code_url", code_url);
            map.put("total_fee", String.valueOf(total_fee));
            map.put("out_trade_no", out_trade_no);

            return map;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * @param out_trade_no  订单id
     * @return
     */
    public Map queryPayStatus(String out_trade_no) {

        Map param = new HashMap();
        param.put("appid", APPID);
        param.put("mch_id", MCH_ID);
        param.put("out_trade_no", out_trade_no);
        param.put("nonce_str", WXPayUtil.generateNonceStr());
        try {
            String xmlParam = WXPayUtil.generateSignedXml(param, KEY);
            HttpUtil client = new HttpUtil(QRY_URL);
            client.setHttps(true);
            client.setXmlParam(xmlParam);
            client.post();
            String result = client.getContent();
            Map<String, String> map = WXPayUtil.xmlToMap(result);

            if (map.get("err_code") != null && map.get("err_code").equals("ORDERNOTEXIST")) {
                System.out.println("订单不存在!");
            }
            if (map.get("trade_state").equals("SUCCESS")) {
                //支付成功,未支付为:NOTPAY
            }

            return map;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

3、控制层

@RestController
@CrossOrigin
@RequestMapping("/order")
public class PayController {

	@Resource
	WxConfig config;

	@PostMapping("/createPay")
    public BusiResult createPayOrder(@RequestBody PayVo payVo) throws JsonProcessingException {
        //向微信发起调用生成预付链接
        Map res = config.createNative(payVo.getOrderId(),
                                            payVo.getFee(),
                                            payVo.getExpirTime());
        System.out.println(res);
        return BusiResult.success(res);
    }
    //生成二维码图片
    @GetMapping("getImg")
	public void getImg(String code_url){
		if(code_url == null) throw new NullPointerException();

		 try {
                //生成二维码配置
                Map<EncodeHintType, Object> hints = new HashMap<>();
                // 设置纠错等级
                hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
                // 编码类型
                hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");

                BitMatrix bitMatrix = new MultiFormatWriter().encode(code_url, BarcodeFormat.QR_CODE, 400, 400, hints);
                OutputStream outputStream =  WebServletUtil.getResponse().getOutputStream();

                MatrixToImageWriter.writeToStream(bitMatrix, "png", outputStream);

            } catch (Exception e){
                e.printStackTrace();
            }
	}

    @PostMapping("/queryPayStatus")
    public BusiResult queryPayStatus(@RequestBody PayVo payVo){
        //向微信发起调用生成预付链接
        Map res = config.queryPayStatus(payVo.getOrderId());
        System.out.println(res);
        return BusiResult.success(res);
    }
}

4、配置文件

payconfig.properties

#公众号appleId
APPID=?
#商户号
MCH_ID=?
#商户密钥
KEY=?
#APP和网页支付提交用户端ip, Native支付填调用微信支付API的机器IP, 即:服务器ip地址
SPBILL_CREATE_IP=127.0.0.1
#接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。(需要配置)
NOTIFY_URL=http://225m5x.natappfree.cc/page/notify
#支付方式,取值如下:JSAPI,NATIVE,APP
TRADE_TYPE=NATIVE
# 微信支付 - 统一下单地址
PLACEANORDER_URL=https://api.mch.weixin.qq.com/pay/unifiedorder

QUERY_URL=https://api.mch.weixin.qq.com/pay/orderquery

5、测试

5.1、访问doc.html

5.2、获取二维码

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值