微信支付API v3 Native支付

废话不多说直接上代码  不熟悉的直接私信我

依赖

<dependency>
   <groupId>com.github.wechatpay-apiv3</groupId>
   <artifactId>wechatpay-apache-httpclient</artifactId>
   <version>0.4.2</version>
</dependency>

配置类(填写自己的配置)

/**
 * 微信支付配置信息
 */
@PropertySource(value = {"classpath:wxpayConfig.properties"})
@Component
public class WxPayConfigure {

    private static final Logger log = LoggerFactory.getLogger(WxPayConfigure.class);

    @Value("${NOTIFY_URL}")
    private String NOTIFY_URL;
    @Value("${MCH_ID}")
    private String MCH_ID; // 商户号
    @Value("${MCH_SERIAL_NO}")
    private String MCH_SERIAL_NO; // 商户证书序列号
    // 你的商户私钥
    @Value("${API_V3_KEY}")
    private String API_V3_KEY;
    @Value("${APP_ID}")
    private String APP_ID;
    @Value("${PACKAGE}")
    private String PACKAGE; //签名固定字符串(必须)
    // 商户私钥
    @Value("${PRIVATE_KEY}")
    private String PRIVATE_KEY;
    //你的微信支付平台证书
    @Value("${CERTIFICATE}")
    private String certificate;

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

    public String getWxDomainUrl() {
        return wxDomainUrl;
    }

    public void setWxDomainUrl(String wxDomainUrl) {
        this.wxDomainUrl = wxDomainUrl;
    }

    public String getNOTIFY_URL() {
        return NOTIFY_URL;
    }

    public void setNOTIFY_URL(String NOTIFY_URL) {
        this.NOTIFY_URL = NOTIFY_URL;
    }

    public String getMCH_ID() {
        return MCH_ID;
    }

    public void setMCH_ID(String MCH_ID) {
        this.MCH_ID = MCH_ID;
    }

    public String getMCH_SERIAL_NO() {
        return MCH_SERIAL_NO;
    }

    public void setMCH_SERIAL_NO(String MCH_SERIAL_NO) {
        this.MCH_SERIAL_NO = MCH_SERIAL_NO;
    }

    public String getAPI_V3_KEY() {
        return API_V3_KEY;
    }

    public void setAPI_V3_KEY(String API_V3_KEY) {
        this.API_V3_KEY = API_V3_KEY;
    }

    public String getAPP_ID() {
        return APP_ID;
    }

    public void setAPP_ID(String APP_ID) {
        this.APP_ID = APP_ID;
    }

    public String getPACKAGE() {
        return PACKAGE;
    }

    public void setPACKAGE(String PACKAGE) {
        this.PACKAGE = PACKAGE;
    }

    public String getPRIVATE_KEY() {
        return PRIVATE_KEY;
    }

    public void setPRIVATE_KEY(String PRIVATE_KEY) {
        this.PRIVATE_KEY = PRIVATE_KEY;
    }

    public String getCertificate() {
        return certificate;
    }

    public void setCertificate(String certificate) {
        this.certificate = certificate;
    }

    public WxPayConfigure() {
    }

    /**
     * 获取商户秘钥
     * @return
     */
    private PrivateKey getPrivateKey(){
        PrivateKey privateKey = PemUtil.loadPrivateKey(PRIVATE_KEY);
        return privateKey;
    }


    /**
     * 获取签名验证器 启动加载一次
     * @return
     * @throws NotFoundException
     */
    @Bean
    public Verifier getVerifier() throws NotFoundException {
        //获取私钥
        PrivateKey privateKey = getPrivateKey();
        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        try {
            certificatesManager.putMerchant(MCH_ID, new WechatPay2Credentials(MCH_ID,
                    new PrivateKeySigner(MCH_SERIAL_NO, privateKey)), API_V3_KEY.getBytes(StandardCharsets.UTF_8));
            //... 若有多个商户号,可继续调用putMerchant添加商户信息
        } catch (IOException | HttpCodeException | GeneralSecurityException e) {
            log.error("微信商户私钥加载失败={}",e.getMessage());
        }
        // 从证书管理器中获取verifier
        return certificatesManager.getVerifier(MCH_ID);
    }


    /**
     * 获取微信支付http请求对象并且只加载一次
     * @param verifier
     * @return
     */
    @Bean
    public  CloseableHttpClient getWxPayClient(Verifier verifier){
        //获取商户私钥
        PrivateKey privateKey = getPrivateKey();
        // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(MCH_ID, MCH_SERIAL_NO, privateKey)
                .withValidator(new WechatPay2Validator(verifier));

        CloseableHttpClient httpClient = builder.build();

        /**
         * 使用WechatPayHttpClientBuilder需要调用withWechatPay设置微信支付平台证书,
         * 而平台证书又只能通过调用获取平台证书接口下载。为了解开"死循环",
         * 你可以在第一次下载平台证书时,按照下述方法临时"跳过”应答签名的验证。
         */
//        CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
//                .withMerchant(MCH_ID, MCH_SERIAL_NO, privateKey)
//                .withValidator(response -> true) // NOTE: 设置一个空的应答签名验证器,**不要**用在业务请求
//                .build();
        return httpClient;
    }

}

二维码工具类:

public class QrUtil {

   public static String qrBase64Str(String url) throws Exception{
      String base64Str = null;
      ByteArrayOutputStream out = null;

       try {

          out = QRCode.from(url).to(ImageType.JPG).withSize(250, 250).stream();
           BASE64Encoder encoder = new BASE64Encoder();
              // 返回Base64编码过的字节数组字符串
           base64Str = encoder.encode(out.toByteArray());
         } finally {
            if (null != out) {
               out.close();
            }
         }
       return base64Str;
   }

@Service
public class WxPayUtil {



    private static Log log = LogFactory.getLog(WxPayUtil.class);
    @Autowired
    private WxPayConfigure wxPayConfigure;
    @Autowired
    private MyConfiguration myConfiguration;


    /**
     * 商户Native支付下单接口,微信后台系统返回链接参数code_url,商户后台系统将code_url值生成二维码图片,用户使用微信客户端扫码后发起支付。
     */
    public String createOrder(PayParams payParams, HttpServletResponse response){
//        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native");
        HttpPost httpPost = new HttpPost(WxApiType.NATIVE_PAY.getValue());
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type","application/json; charset=utf-8");
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode rootNode = objectMapper.createObjectNode();

        //元化为分
        BigDecimal bigDecimal = new BigDecimal(payParams.getTotalAmount());
        BigDecimal str = new BigDecimal("100");
        BigDecimal moneyResult = bigDecimal.multiply(str);
        //appid  微信生成的应用ID,全局唯一。 必填
        //mchid  直连商户号    必填
        //description  商品描述        必填
        //out_trade_no  商户订单号 商户系统内部订单号  必填
        //  time_expire  交易结束时间   非必填 订单失效时间
        //attach   附加数据
        //notify_url 必填   回调url   必填
        //amount  + 订单金额    total int类型(微信要求的)     必填   currency  货币类型  CNY(人民币)  非必填
        rootNode.put("mchid", wxPayConfigure.getMCH_ID())
                .put("appid",wxPayConfigure.getAPP_ID() )
                .put("description", "日照市中心医院自助缴费")
                .put("notify_url", wxPayConfigure.getNOTIFY_URL())
                //商户订单号  商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
//                .put("out_trade_no", payParams.getOutTradeNo());
                .put("out_trade_no", payParams.getOutTradeNo());
        rootNode.putObject("amount")
                .put("total", moneyResult.intValue());
//                .put("total", 1);
//        rootNode.putObject("payer")
//                .put("openid", "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o");

        String codeUrl="";
        try {
            objectMapper.writeValue(bos, rootNode);
            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            CloseableHttpResponse closeableHttpResponse = null;
            CloseableHttpClient wxPayClient = wxPayConfigure.getWxPayClient(wxPayConfigure.getVerifier());
            closeableHttpResponse = wxPayClient.execute(httpPost);
            String bodyAsString = EntityUtils.toString(closeableHttpResponse.getEntity());
            ObjectMapper mapper = new ObjectMapper();
            JsonNode jsonNode = mapper.readTree(bodyAsString);
            //二维码url
            codeUrl = jsonNode.get("code_url").asText();
        } catch (IOException | NotFoundException e) {
            e.printStackTrace();
        }
        String qrCodePath = myConfiguration.getQrCode();
        String  filePath = String.format(qrCodePath+"/qr-%s.jpg",
                payParams.getOutTradeNo());
//                log.info("filePath:" + filePath);
        ZxingUtils.getQRCodeImge(codeUrl, 256, filePath);
        //用流读取显示二维码
        File file = new File(filePath);
        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            ImageIO.write(ImageIO.read(file),"jpg",outputStream);
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //最后删除生成的图片
        FileUtil.deleteFile(filePath);
        return null;
    }


    /**
     * 微信查询订单   查询订单可通过微信支付订单号和商户订单号两种方式查询,两种查询方式返回结果相同
     */

    //  微信支付订单号查询   1217752501201407033233368018 微信支付订单号   1230000109 商户号
    //  get  请求URL: https://api.mch.weixin.qq.com/v3/pay/transactions/id/{transaction_id}
    // https://api.mch.weixin.qq.com/v3/pay/transactions/id/1217752501201407033233368018?mchid=1230000109


    //商户订单号查询    1217752501201407033233368018 商户订单号    1230000109商户号
    //  商户订单号查询  get  请求URL: https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}
    // https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/1217752501201407033233368018?mchid=1230000109


    public String queryWxOrder( PayParams payParams){
        URIBuilder uriBuilder = null;
        try {
//            uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/"+payParams.getOutTradeNo()+"?mchid="+wxPayConfigure.getMCH_ID());
            uriBuilder = new URIBuilder(WxApiType.ORDER_QUERY_BY_NO.getValue()+payParams.getOutTradeNo()+"?mchid="+wxPayConfigure.getMCH_ID());
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        HttpGet httpGet = null;
        try {
            assert uriBuilder != null;
            httpGet = new HttpGet(uriBuilder.build());
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        assert httpGet != null;
        httpGet.addHeader("Accept", "application/json");
        CloseableHttpResponse response = null;
        CloseableHttpClient wxPayClient = null;
        try {
            wxPayClient = wxPayConfigure.getWxPayClient(wxPayConfigure.getVerifier());
        } catch (NotFoundException e) {
            e.printStackTrace();
        }
        try {
            assert wxPayClient != null;
            response = wxPayClient.execute(httpGet);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String bodyAsString = null;
        try {
            assert response != null;
            bodyAsString = EntityUtils.toString(response.getEntity());
        } catch (IOException e) {
            e.printStackTrace();
        }
//        System.out.println(bodyAsString);
        ObjectMapper mapper = new ObjectMapper();
        String tradeStateDesc ="";
        try {
            JsonNode jsonNode = mapper.readTree(bodyAsString);
//            Map<String,String> map = mapper.convertValue(bodyAsString, Map.class);
             tradeStateDesc = jsonNode.get("trade_state_desc").asText();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return tradeStateDesc;
    }


    /**
     * 关闭订单  待测试
     * @param payParams
     */
    public void closeWxOrder(PayParams payParams){
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/"+payParams.getOutTradeNo()+"/close");
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type","application/json; charset=utf-8");

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectMapper objectMapper = new ObjectMapper();

        ObjectNode rootNode = objectMapper.createObjectNode();

        rootNode.put("mchid",wxPayConfigure.getMCH_ID());

        CloseableHttpResponse response = null;
        String bodyAsString = null;
        try {
            objectMapper.writeValue(bos, rootNode);
            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            CloseableHttpClient wxPayClient = wxPayConfigure.getWxPayClient(wxPayConfigure.getVerifier());
            response = wxPayClient.execute(httpPost);
            bodyAsString = EntityUtils.toString(response.getEntity());
        } catch (IOException | NotFoundException e) {
            e.printStackTrace();
        }

        int statusCode = response.getStatusLine().getStatusCode();//204 正常

        System.out.println(bodyAsString);
    }


    /**
     * 申请退款
     * @param payParams
     * @return
     */
    public String refundOrder(PayParams payParams){
        HttpPost httpPost = new HttpPost(WxApiType.REFUND_ORDER_BY_NO.getValue());
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type","application/json; charset=utf-8");
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode rootNode = objectMapper.createObjectNode();
        //元化为分
        BigDecimal str = new BigDecimal("100");
        BigDecimal totalBigDecimal = new BigDecimal(payParams.getTotalAmount());
        BigDecimal totalMoneyResult = totalBigDecimal.multiply(str);

        BigDecimal refundBigDecimal = new BigDecimal(payParams.getRefundAmount());
        BigDecimal refundMoneyResult = refundBigDecimal.multiply(str);
        //appid  微信生成的应用ID,全局唯一。 必填
        //mchid  直连商户号    必填
        //description  商品描述        必填
        //out_trade_no  商户订单号 商户系统内部订单号  必填
        //  time_expire  交易结束时间   非必填 订单失效时间
        //attach   附加数据
        //notify_url 必填   回调url   必填
        //amount  + 订单金额    total int类型(微信要求的)     必填   currency  货币类型  CNY(人民币)  非必填
        //商户订单号  商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
        rootNode.put("out_trade_no", payParams.getOutTradeNo())
                .put("out_refund_no",payParams.getRefundTradeNo())
                .put("reason", "正常退款");
        rootNode.putObject("amount")
                .put("total", totalMoneyResult.intValue())
                .put("refund", refundMoneyResult.intValue())
        .put("currency","CNY");
        String status="";
//        String reason="";
        try {
            objectMapper.writeValue(bos, rootNode);
            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            CloseableHttpResponse response = null;
            CloseableHttpClient wxPayClient = wxPayConfigure.getWxPayClient(wxPayConfigure.getVerifier());
            response = wxPayClient.execute(httpPost);
            String bodyAsString = EntityUtils.toString(response.getEntity());
            ObjectMapper mapper = new ObjectMapper();
            JsonNode jsonNode = mapper.readTree(bodyAsString);
            //SUCCESS:退款成功
            //CLOSED:退款关闭
            //PROCESSING:退款处理中
            //ABNORMAL:退款异常
            status = jsonNode.get("status").asText();
//            reason = jsonNode.get("reason").asText();
        } catch (IOException | NotFoundException e) {
            e.printStackTrace();
        }
        //
        return status;
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值