Java实现微信扫码支付V3(NATIVE方式)[全网最简单]

前期了解准备

微信商户账号
地址为https://pay.weixin.qq.com 用来开通微信支付能力,没有商户号是无法使用微信支付的。而且后续申请的公众号 appid 和移动应用、小程序的 appid 都要同微信商户帐号进行绑定。

微信开放平台账号
地址为https://open.weixin.qq.com 用来开发第三方平台、移动应用、公众平台、网站应用的开发。后续申请的微信公众号服务号、移动应用 appid 需要绑定到开放平台中。

微信公众平台服务号
通过https://mp.weixin.qq.com申请, 切记是服务号,不是订阅号,也不是个人号!服务号才是企业开发用的。申请认证完毕后需要同微信商户帐号和微信开放平台帐号进行绑定。

下面是为了获取开发中需要的参数:标识商户身份的信息、商户的证书和私钥、微信支付的证书、微信支付API的URL

  • 1.获取商户号

    微信商户平台:https://pay.weixin.qq.com/ 步骤:申请成为商户 => 提交资料 => 签署协议 => 获取商户号

  • 2.获取AppID

    微信公众平台:https://mp.weixin.qq.com/ 步骤:注册服务号 => 服务号认证 => 获取APPID => 绑定商户号

  • 3.申请商户证书

    步骤:登录商户平台 => 选择 账户中心 => 安全中心 => API安全 => 申请API证书 包括商户证书和商户私钥

  • 4.获取微信的证书

    可以预先下载,也可以通过编程的方式获取。

  • 5.获取APIv3秘钥(在微信支付回调通知和商户获取平台证书使用APIv3密钥)

    步骤:登录商户平台 => 选择 账户中心 => 安全中心 => API安全 => 设置APIv3密钥

1.引入依赖

<!--wechatpay-sdk-->
<dependency>
    <groupId>com.github.wechatpay-apiv3</groupId>
    <artifactId>wechatpay-apache-httpclient</artifactId>
    <version>0.4.5</version>
</dependency>

2.添加yml

pay:
wechat:
appId: xxxxx
appSecret: xxxx
mchId: xxx
#商户私钥路径
keyPath: Dcerts/apiclient_key.pem
#三个证书路径
certPath: certs/apiclient_cert.pem
certP12Path: certs/apiclient_cert.p12
platformCertPath: certs/platformCert.pem
#apiv2秘钥
apiKey: xx
#apiv3秘钥
apiKey3: xxx
#可外网访问域名
domain: http://energy.free.idcfengye.com/
#商户证书序列号
serialnumber: xxxx

3.添加配置类

package com.legendenergy.config;

import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
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.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;

@Configuration
public class WechatpayConfig {

    @Value("${pay.wechat.mchId}")
    private String merchantId;

    @Value("${pay.wechat.apiKey3}")
    private String apiV3Key;

    @Value("${pay.wechat.serialnumber}")
    private String merchantSerialNumber;

    @Value("${pay.wechat.keyPath}")
    private String privateKey;


    /**
     * 给容器中加入WechatPay的HttpClient,虽然它是WechatPay的,
     * 但可以用它给任何外部发请求,因为它只对发给WechatPay的请求做处理而不对发给别的的请求做处理.
     *
     * @return
     */
    @Bean
    public CloseableHttpClient closeableHttpClient() throws  IOException {
        //获取商户私钥方法一
        //String key = FileUtil.readUtf8String(privateKey);
        //PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(key);
        // 获取商户私钥  下面三行代码通过流获取私钥可以避免打jar包到服务器后找不到私钥文件
        Resource[] resources = new PathMatchingResourcePatternResolver().getResources(privateKey);
        InputStream inputStream = resources[0].getInputStream();
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(inputStream);
        //微信证书校验器
        Verifier verifier = null;
        try {
            //获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            //向证书管理器增加需要自动更新平台证书的商户信息(默认时间间隔:24小时)
            certificatesManager.putMerchant(merchantId, new WechatPay2Credentials(merchantId, new PrivateKeySigner(merchantSerialNumber, merchantPrivateKey)), apiV3Key.getBytes(StandardCharsets.UTF_8));
            //从证书管理器中获取verifier
            verifier = certificatesManager.getVerifier(merchantId);
        } catch (Exception e) {
            new RuntimeException("微信证书校验器配置失败");
        }
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)
                .withValidator(new WechatPay2Validator(verifier));
        CloseableHttpClient httpClient = builder.build();
        return httpClient;
    }
    /**
     * 和上面相比只是不需要验证签名了
     * @return
     */
//    @Bean
//    public CloseableHttpClient httpClientWithNoSign(){
//        //私钥
//        PrivateKey merchantPrivateKey=PemUtil.loadPrivateKey(privateKey);
//        //微信证书校验器
//        Verifier verifier=null;
//        try{
//            //获取证书管理器实例
//            CertificatesManager certificatesManager=CertificatesManager.getInstance();
//            //向证书管理器增加需要自动更新平台证书的商户信息(默认时间间隔:24小时)
//            certificatesManager.putMerchant(merchantId,new WechatPay2Credentials(merchantId,new PrivateKeySigner(merchantSerialNumber,merchantPrivateKey)),apiV3Key.getBytes(StandardCharsets.UTF_8));
//            //从证书管理器中获取verifier
//            verifier=certificatesManager.getVerifier(merchantId);
//        }
//        catch(Exception e){
//            new RuntimeException("微信证书校验器配置失败");
//        }
//        WechatPayHttpClientBuilder builder=WechatPayHttpClientBuilder.create()
//                                                                     .withMerchant(merchantId,merchantSerialNumber,merchantPrivateKey)
//                                                                     .withValidator(response->true);
//        CloseableHttpClient httpClient=builder.build();
//        return httpClient;
//    }
}

  

4.添加API常量  

public class WechatPayApi {
    /**
     * 微信支付主机地址
     */
    public static final String HOST = "https://api.mch.weixin.qq.com";
 
 
    /**
     * Native下单
     */
    public static final String NATIVE_ORDER = HOST+ "/v3/pay/transactions/native";
 
 
 
    /**
     * Native订单状态查询, 根据商户订单号查询
     */
    public static final String NATIVE_QUERY = HOST+ "/v3/pay/transactions/out-trade-no/%s?mchid=%s";

 
    /**
     * 关闭订单接口
     */
    public static final String NATIVE_CLOSE_ORDER = HOST+ "/v3/pay/transactions/out-trade-no/%s/close";
 
 
 
    /**
     * 申请退款接口
     */
    public static final String NATIVE_REFUND_ORDER = HOST+ "/v3/refund/domestic/refunds";
    /**
     * 退款状态查询接口
     */
    public static final String NATIVE_REFUND_QUERY = HOST+ "/v3/refund/domestic/refunds/%s";
 
}

5.测试查询订单接口

   String url = String.format(WechatPayApi.NATIVE_QUERY, tradeNo, merchantId);
   HttpGet httpGet = new HttpGet(url); httpGet.setHeader("Accept", "application/json"); CloseableHttpResponse response = wxPayClient.execute(httpGet); String bodyString = EntityUtils.toString(response.getEntity()); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == 200) { //模拟微信支付回调成功后的操作 }

 https://blog.csdn.net/u012488804/article/details/113378063  微信回调密文解析但是明文不解析

 

posted @ 2022-11-13 23:50  江南大才子  阅读(1831)  评论(0编辑  收藏  举报