java APP微信支付API V3

本文记录了使用Java实现微信支付V3的详细步骤,包括接入前准备、开发环境配置、API接口使用及接口规则。特别强调了签名生成、证书管理与回调报文加密解密的重要性。在实际开发中,遇到前端无法获取支付信息的问题,解决方案是后端通过定时查询订单状态来验证支付结果。
摘要由CSDN通过智能技术生成

因项目需要,有用到微信支付,这里对java微信支付的开发流程和注意事项到做一次记录,以遍后面有需要的时候翻阅,方便回顾。

快速开发一个功能,需要了解整个开发过程以及开发过程中需要注意的点,开发的功能才能足够安全高效

如下是微信支付官方给出的微信支付V3流程图:

微信支付V3开发流程阅读下面代码时,需要对照当前流程):

1、首先是接入前准备

  • 选择接入模式
  • 参数申请
  • 配置API key
  • 下载并配置商户证书
  • App支付页面规范

具体参考微信支付V3接入前准备:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_5_1.shtml

2、开发准备

搭建和配置开发环境,根据自身开发语言,选择对应的开发库构建项目,笔者这里使用的是Java,所以使用的是wechatpay-apache-httpclient,只要将对应的maven依赖引入项目即可

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

,最新依赖版本可参考https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient

3、API接口列表

需要注意的是接口的适用接入模式,请求参数,接口地址,返回参数一定要跟微信官方文档的一致。

4、接口规则

  • 签名生成:微信支付Api v3 key要求商户对请求进行签名,微信支付会在收到请求后进行签名的验证。如果验证不通过,微信支付Api v3会拒绝处理请求。返回状态401
  • 签名验证:微信支付会在回调的Http头部中包括回调报文的签名,以确保回调是由微信支付发送
  • 证书和回调报文加密解密:为了保证安全性,微信支付在回调通知和平台证书下载接口中,对关键信息进行了AES-256-GCM加密
  • 平台证书更新:由于平台证书存在有效期,需要定时更换平台证书以确保交易安全

微信支付V3java 代码:

配置信息

wechat:
  appId: ###
  mchId: ###
  aesKey: ###
  unifiedOrder:
    url: https://api.mch.weixin.qq.com/v3/pay/transactions/app
  notify:
    url: ###
  queryOrder:
    url: https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/%s?mchid=%s
  certificates:
    url: https://api.mch.weixin.qq.com/v3/certificates
package com.hjy.ft.config;

import com.hjy.pay.WxpayV3Util;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.io.*;
import java.security.cert.X509Certificate;

/**
 * @version 1.0
 * @className WeChatStartUpRunner
 * @description 程序启动后加载
 * @since 2021/4/19 14:47
 */
@Component
@Order(value = 1)
public class WeChatStartUpRunner implements CommandLineRunner {

    /**
     * 微信商户号
     */
    @Value("${wechat.mchId}")
    private String wechatMchId;

    /**
     * 应用id
     */
    @Value("${wechat.appId}")
    private String wechatAppId;

    /**
     * API v3密钥
     */
    @Value("${wechat.aesKey}")
    private String wechatAesKey;

    /**
     * 统一下单地址
     */
    @Value("${wechat.unifiedOrder.url}")
    private String unifiedOrderUrl;

    /**
     * 异步接收微信支付 回调地址
     */
    @Value("${wechat.notify.url}")
    private String notifyUrl;

    /**
     * 微信订单查询地址
     */
    @Value("${wechat.queryOrder.url}")
    private String queryOrderUrl;

    /**
     * 获取平台证书列表
     */
    @Value("${wechat.certificates.url}")
    private String certificatesUrl;

    @Override
    public void run(String... args) throws Exception {
        WxpayV3Util.wechatMchId = wechatMchId;
        WxpayV3Util.wechatAppId = wechatAppId;
        WxpayV3Util.wechatAesKey = wechatAesKey;
        WxpayV3Util.unifiedOrderUrl = unifiedOrderUrl;
        WxpayV3Util.notifyUrl = notifyUrl;
        WxpayV3Util.queryOrderUrl = queryOrderUrl;
        X509Certificate certificate = PemUtil.loadCertificate(new FileInputStream(readPayPath("apiclient_cert.pem")));
        WxpayV3Util.wechatCertificatePath = certificate;
        //获取证书序列号
        WxpayV3Util.serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
        WxpayV3Util.wechatKeyPath = PemUtil.loadPrivateKey(new FileInputStream(readPayPath("apiclient_key.pem")));
        WxpayV3Util.certificatesUrl = certificatesUrl;
        //获取平台证书(由于微信证书存在有限期限制,微信支付会不定期更换平台证书以确保交易安全)
        WxpayV3Util.certificateMap = WxpayV3Util.refreshCertificate();
    }

    /**
     * 读取文件地址,适用发布环境
     * @param fileName (文件路径)
     * @return 临时文件路径
     */
    public String readPayPath(String fileName) {
        String url = null;
        //返回读取指定资源的输入流
        InputStream is = this.getClass().getResourceAsStream("/wxpay/"+fileName);
        //InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("/alipay/"+fileName);
        String path = System.getProperty("user.dir");
        //create folder
        String dirPath = path + File.separator + "uploadWxPayFiles";
        File dir = new File(dirPath);
        dir.mkdirs();
        //create file
        String filePath = dirPath + File.separator + fileName;
        File file = new File(filePath);
        //判断文件是否存在
        if (!file.exists()) {
            try {
                file.createNewFile();
                //文件不存,创建流输入数据到新文件
                inputStreamToFile(is, file);
            } catch (IOException e) {
                e.printStackTrace();
            }
            url = filePath;
        }else{
            url = filePath;
        }
        return url;
    }

    public void inputStreamToFile(InputStream ins, File file) {
        OutputStream os = null;
        try {
            os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[1024];
            while ((bytesRead = ins.read(buffer, 0, 1024)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值