payment:
  wechat:
    # 应用号
    appid: 123456
    # 商户号
    mchid: 123456
    # 商户证书序列号
    mch-cert-no: 123456
    # 商户私钥文件
    private-key-path: payment/apiclient_key.pem
    # 回调地址
    callback: https://www.apy.com
    # 服务号的 appsecret
    secret: 123456
    # 微信支付公钥ID
    public-key-id: 123456

1 微信支付 后端 Token

/**
 * 获取微信 AccessToken 接口
 */
private static final String ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?appid={}&secret={}&grant_type=client_credential";
public String getAccessToken() {
    String sn = IdUtils.nextIdStr();
    log.info("获取微信AccessToken开始 SN:{}", sn);
    try {
        log.info("获取微信AccessToken请求 SN:{}, URL:{}", sn, StrUtil.format(ACCESS_TOKEN, proper.getAppid(), proper.getSecret()));
        String response = HttpUtil.get(StrUtil.format(ACCESS_TOKEN, proper.getAppid(), proper.getSecret()));
        log.info("获取微信AccessToken结束 SN:{}, REP:{}", sn, response);

        if (!JSONUtil.isTypeJSON(response)) {
            return "";
        }

        return JSONUtil.parseObj(response).getStr("access_token", "");
    } catch (Exception e) {
        log.error("获取微信AccessToken异常 SN:{}", sn, e);
    }
    return "";
}

2 微信支付 后端 Ticket

/**
 * 获取微信 JsapiTicket 接口
 */
private static final String JSAPI_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={}&type=jsapi";
public String getJsapiTicke(String token) {
    String sn = IdUtils.nextIdStr();
    log.info("获取微信JsapiTicket开始 SN:{}, Token:{}", sn,  token);
    try {

        log.info("获取微信JsapiTicket请求 SN:{}, URL:{}", sn, StrUtil.format(JSAPI_TICKET, token));
        String response = HttpUtil.get(StrUtil.format(JSAPI_TICKET, token));
        log.info("获取微信JsapiTicket结束 SN:{}, REP:{}", sn, response);

        if (!JSONUtil.isTypeJSON(response)) {
            return "";
        }

        return JSONUtil.parseObj(response).getStr("ticket", "");
    } catch (Exception e) {
        log.error("获取微信JsapiTicket异常 SN:{}", sn, e);
    }
    return "";
}

3 微信支付 后端 签名

url就是当前H5页面的URL

public AjaxResult jsapiInitialize(String url) {
    try {
        // 1、获取AccessToken
        String token = wechatService.getAccessToken();
        // 2、获取Ticket
        String ticket = wechatService.getJsapiTicke(token);
        // 3、随机字符串
        String string = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
        // 4、时间戳
        long timestamp = System.currentTimeMillis() / 1000;
        // 5、将参数排序并拼接字符串
        String str = StrUtil.format("jsapi_ticket={}&noncestr={}&timestamp={}&url={}", ticket, string, timestamp, url);
        Map<String, Object> info = new HashMap<>();
        info.put("appid", payProper.getAppid());
        info.put("timestamp", timestamp);
        info.put("noncestr", string);
        info.put("signature", PayUtil.sha1(str));
        return AjaxResult.success(info);
    } catch (Exception e) {
        log.error("微信JSAPI初始化失败!", e);
        return AjaxResult.error("微信JSAPI初始化失败!");
    }
}
/**
 * SHA1加密核心方法
 *
 * @param input 待加密字符串
 * @return 40位十六进制SHA1加密结果
 */
public static String sha1(String input) {
    // 空值处理
    if (input == null || input.isEmpty()) {
        return "";
    }
    try {
        // 1. 获取SHA-1算法的MessageDigest实例
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        // 2. 将字符串转换为字节数组(指定UTF-8编码,避免编码不一致)
        byte[] inputBytes = input.getBytes(StandardCharsets.UTF_8);
        // 3. 更新摘要(传入待加密字节数组)
        md.update(inputBytes);
        // 4. 计算哈希摘要(生成20字节的SHA1结果)
        byte[] digestBytes = md.digest();
        // 5. 将字节数组转换为40位十六进制字符串
        return bytesToHex(digestBytes);
    } catch (Exception e) {
        log.error("SHA1算法异常", e);
        return "";
    }
}

/**
 * 字节数组转十六进制字符串(核心工具方法)
 *
 * @param bytes 待转换的字节数组
 * @return 十六进制字符串
 */
public static String bytesToHex(byte[] bytes) {
    StringBuilder hexStr = new StringBuilder();
    for (byte b : bytes) {
        // 将字节转换为无符号整数(& 0xFF 避免负数)
        int num = b & 0xFF;
        // 转换为十六进制,不足两位补0
        String hex = Integer.toHexString(num);
        if (hex.length() < 2) {
            hexStr.append("0");
        }
        hexStr.append(hex);
    }
    return hexStr.toString();
}

4 微信支付 前端 Vue wx.config

wx.config({
  debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  appId: data.appid, // 必填,服务号的唯一标识
  timestamp: data.timestamp, // 必填,生成签名的时间戳(后端生成)
  nonceStr: data.noncestr, // 必填,生成签名的随机串(后端生成)
  signature: data.signature, // 必填,签名(后端生成)
  jsApiList: ["chooseWXPay"], // 必填,需要使用的JS接口列表
});

wx.ready(() => {
  this.wxReady = true;
  wx.checkJsApi({
    jsApiList: ["chooseWXPay"],
    success: function (res) {
      console.log("初始化成功");
    },
  });
});

wx.error(function (res) {
  console.log("初始化失败");
});
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐