相关文章推荐
儒雅的豆芽  ·  C#实现一个最简单的HTTP服务器 - 小y ·  2 天前    · 
长情的充电器  ·  MyBatis 3 | Mapper ...·  昨天    · 
爱热闹的海龟  ·  入力検証時に表示される既定のメッセージの多言 ...·  昨天    · 
帅呆的茴香  ·  Asp.Net Core ...·  昨天    · 
豪爽的西装  ·  RenderSettings | rhino3dm·  9 小时前    · 
任性的手电筒  ·  深圳组工在线·  10 月前    · 
腼腆的椅子  ·  江苏省人民政府 要闻关注 ...·  11 月前    · 
侠义非凡的小蝌蚪  ·  2020年5月_大事记_云南省人民政府门户网站·  1 年前    · 
鼻子大的煎饼果子  ·  石景山区小升初公办校招生名单_石景山区优质公 ...·  1 年前    · 
叛逆的斑马  ·  极星3,专“割”有钱人_手机新浪网·  1 年前    · 
Code  ›  微信支付v3接口 回调+回调验签 java示例代码 | 微信开放社区
string
https://developers.weixin.qq.com/community/develop/article/doc/000c4a859f015003113d7192551413
没人理的绿豆
1 年前

交流专区
服务市场
微信学堂
文档
小程序
  • 常用主页

    小程序

    小游戏

    企业微信

    微信支付

  • 服务市场
    微信学堂
    文档
登录
评论

置顶 微信支付v3接口 回调+回调验签 java示例代码 精选 热门

HOPE 2021-12-14
8205 浏览
7 评论

微信支付v3接口回调接口java示例代码

这里使用的是springboot框架进行测试,比较方便简单,代码仅供参考

原理:java 的前后端通信

注意 :1、域名一般需要备案:如果没有备案可能会被拦截,无法正常应答验签(申请域名的平台都会提供备案的攻略,按照攻略正常备案即可)

2、一般无法本地测试(也是就是个人pc电脑),因为没有固定的ip地址,需要申请购买一个服务器后,有固定的对外ip(记得把对应默认端口后80打开,不然会被拦截),把对应的ip映射到对应的域名后(映射其实就是绑定的意思,在申请到域名后设置一下,比较简单),看看外网能不能ping通,如果无法ping通就说明没有映射成功,或者映射的ip不是外网可以访问

pox文件:

4.0.0org.springframework.bootspring-boot-starter-parent2.4.3 cn.hzldemo0.0.1-SNAPSHOTjardemoDemo project for Spring Boot1.82.9.2org.springframework.bootspring-boot-starterorg.springframework.bootspring-boot-starter-testtest
        org.springframework.bootspring-boot-starter-web
        com.github.wechatpay-apiv3wechatpay-apache-httpclient0.2.3org.projectlomboklombokcom.squareup.okhttp3okhttp3.14.9org.springframeworkspring-tx5.3.1io.springfoxspringfox-swagger2${swagger2.version}io.springfoxspringfox-swagger-ui${swagger2.version}com.alibabafastjson1.2.60
        com.github.wechatpay-apiv3wechatpay-apache-httpclient0.2.3
    org.springframework.bootspring-boot-maven-plugin

启动类:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);


配置文件:(application.yml)只配置了默认的端口号

server:
  port: 80



回调主要代码:

import com.alibaba.fastjson.JSON;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.Base64Utils;
import




    
 org.springframework.web.bind.annotation.*;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.cert.X509Certificate;
import java.security.*;
import java.util.*;
@RestController
@RequestMapping("/weixin/pay")
public class WeiXinPayController {
      //商户api证书私钥文件的私钥串,apiclient_key.pem文本形式打开即可获取,不需要前后缀
      static String s ="商户api证书私钥文件的私钥串";
      //验签方法,非微信官方的,微信支付官方的基本也查不到,封装的方式不一样,下面也有
      public boolean verify(String srcData, X509Certificate certificate, String sign, String Serial) throws Exception {
          //先验证证书序列号是否正确
          if (certificate.getSerialNumber().toString(16).toUpperCase().equals(Serial)){
              Signature sha256withRSA = Signature.getInstance("SHA256withRSA");
              sha256withRSA.initVerify(certificate.getPublicKey());
              sha256withRSA.update(srcData.getBytes());
              return  sha256withRSA.verify(Base64Utils.decodeFromString(sign));
          }else {
              return false;
       * 微信支付回调地址
      @ApiOperation(value = "微信支付回调地址")
      @PostMapping(value = "/callback/test")//域名后面的路径,可以根据自己的喜好或者业务需求设置,前面是域名,不能携带端口号,比如https://www.baidu.com/weixin/pay/callback/test,  https://www.baidu.com找到你的服务器,/weixin/pay/callback/test服务器的哪个方法进行处理
       * request 请求体
       * response 响应体
      public String   callBack(HttpServletRequest request, HttpServletResponse response) throws IOException, GeneralSecurityException {
          String characterEncoding = request.getCharacterEncoding();
          System.out.println("characterEncoding=" + characterEncoding);
          //从请求头获取验签字段
          String Timestamp = request.getHeader("Wechatpay-Timestamp");
          String Nonce = request.getHeader("Wechatpay-Nonce");
          String Signature = request.getHeader("Wechatpay-Signature");
          String Serial = request.getHeader("Wechatpay-Serial");
          System.out.println("开始读取请求头的信息");
          //请求头
          System.out.println("Wechatpay-Timestamp=" + Timestamp);
          System.out.println("Wechatpay-Nonce=" + Nonce);
          System.out.println("Wechatpay-Signature=" + Signature);
          System.out.println("Wechatpay-Serial=" + Serial);
          System.out.println("=================");
          //加载平台证书,官方的sdk,s为商户api证书私钥
          PrivateKey merchantPrivateKey = PemUtil
                  .loadPrivateKey(new ByteArrayInputStream(s.getBytes("utf-8")));
          //加载官方自动更新证书
          AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                                                                            //商户平台查看                            //不是API密钥                                                  
                  new WechatPay2Credentials("商户号", new PrivateKeySigner("商户api证书序列号", merchantPrivateKey)), "APIv3密钥".getBytes("utf-8"));
          //读取请求体的信息
          System.out.println("开始读取请求体的信息");
          ServletInputStream inputStream = request.getInputStream();
          StringBuffer stringBuffer = new StringBuffer();
          BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
          String s;
          //读取回调请求体
          while ((s = bufferedReader.readLine()) != null) {
              stringBuffer.append(s);
          String s1 = stringBuffer.toString();
          System.out.println("请求体" + s1);
          Map requestMap = (Map) JSON.parse(s1);
          //开始按照验签进行拼接
          String id = requestMap.get("id");
          System.out.println("id=" + id);
          String resource = String.valueOf(requestMap.get("resource"));
          System.out.println("resource=" + resource);
          Map requestMap2 = (Map) JSON.parse(resource);
          String associated_data = requestMap2.get("associated_data");
          String nonce = requestMap2.get("nonce");
          String ciphertext = requestMap2.get("ciphertext");
          //按照文档要求拼接验签串
          String VerifySignature = Timestamp + "\n" + Nonce + "\n" + s1 + "\n";
          System.out.println("拼接后的验签串=" + VerifySignature);
          //使用官方验签工具进行验签
          boolean verify1 = verifier.verify(Serial, VerifySignature.getBytes(), Signature);
          System.out.println("官方工具验签=" + verify1);
        //使用自己写的验签方法进行验签
        //赋一个默认值
        boolean verify = false;
        try {
            verify = verify(VerifySignature, verifier.getValidCertificate(), Signature, Serial);
        } catch (Exception e) {
            e.printStackTrace();
        System.out.println("验签方法进行验签=" + verify);
        //判断验签的结果
        System.out.println("=======判断验签结果=======");
        if (verify == false) {
            System.out.println("验签失败,应答接口");
            Map map = new HashMap<>();
            //响应接口
            //设置状态码
            response.setStatus(500);
            return "{"+
                    '"'+ "code"+'"'+":"+'"'+"FAIL"+'"'+" "+
                    '"'+ "message"+'"'+":"+'"'+"失败"+'"'+
                    "}";
        System.out.println("验签成功后,开始进行解密");
        //解密,如果这里报错,就一定是APIv3密钥错误
        AesUtil aesUtil = new AesUtil("APIv3密钥".getBytes());
        String aes = aesUtil.decryptToString(associated_data.getBytes(), nonce.getBytes(), ciphertext);
        System.out.println("解密后=" + aes);
        Map map = new HashMap<>();
        //响应接口
        map.put("code", "SUCCESS");
        map.put("message", "成功");
        //设置状态码
        response.setStatus(200);
            return "{"+
                   '"'+ "code"+'"'+":"+'"'+"SUCCESS"+'"'+" "+
                   '"'+ "message"+'"'+":"+'"'+"成功"+'"'+
                   "}";


最后一次编辑于 2022-05-27
点赞 1
收藏
分享

扫描小程序码分享

复制链接

删除文章后,文章内容和评论将一并被删除,且不可恢复。

删除 取消
评论
关闭

请选择投诉理由

  • 广告内容
  • 违法违规
  • 恶意灌水内容
  • 其他

7 个评论

  • 星辰
    星辰
    星期一 14:44
    请 登录 后发表内容
    关闭

    新增或编辑超链接

    确认 取消
    关闭

    插入视频

    确认 取消
    发表

    javax.crypto.AEADBadTagException: Tag mismatch!

    这个什么原因呢

    你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

    待楼主反馈
    星期一 14:44
    赞同
    回复 1
    • 星辰
      星辰
      星期一 14:45
      请 登录 后发表内容
      关闭

      新增或编辑超链接

      确认 取消
      关闭

      插入视频

      确认 取消
      发表
      ApiV3Key 是正确的

      你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

      待楼主反馈
      星期一 14:45
      赞
      回复
      关闭

      请选择投诉理由

      • 广告内容
      • 违法违规
      • 恶意灌水内容
      • 其他
    关闭

    请选择投诉理由

    • 广告内容
    • 违法违规
    • 恶意灌水内容
    • 其他
  • Sweethome
    Sweethome
    04-14
    请 登录 后发表内容
    关闭

    新增或编辑超链接

    确认 取消
    关闭

    插入视频

    确认 取消
    发表

    请求头里的四个参数为空是为什么呀

    

    你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

    待楼主反馈
    04-14
    赞同
    回复
    关闭

    请选择投诉理由

    • 广告内容
    • 违法违规
    • 恶意灌水内容
    • 其他
  • 及時行樂
    及時行樂
    02-28
    请 登录 后发表内容
    关闭

    新增或编辑超链接

    确认 取消
    关闭

    插入视频

    确认 取消
    发表

    官方工具总是验签失败咋回事啊?

    请求头里的四个参数和拼接的验签串打印出来都有数据,格式也都没问题

    日志提示验签失败

    你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

    待楼主反馈
    02-28
    赞同
    回复 1
    • HOPE
      HOPE
      03-02
      请 登录 后发表内容
      关闭

      新增或编辑超链接

      确认 取消
      关闭

      插入视频

      确认 取消
      发表
      你把证书打印出来,然后跟单独下的证书对比一下,要注意,使用的是微信支付平台证书

      你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

      待楼主反馈
      03-02
      赞
      回复
      关闭

      请选择投诉理由

      • 广告内容
      • 违法违规
      • 恶意灌水内容
      • 其他
    关闭

    请选择投诉理由

    • 广告内容
    • 违法违规
    • 恶意灌水内容
    • 其他
  • @@
    @@
    2022-11-24
    请 登录 后发表内容
    关闭

    新增或编辑超链接

    确认 取消
    关闭

    插入视频

    确认 取消
    发表

    java.lang.IllegalArgumentException: 无效的ApiV3Key,长度必须为32个字节

    这个密钥是apiv3密钥不是吗

    我的是用的這個

    AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
            //商户平台查看                            //不是API密钥
            new WechatPay2Credentials(wxPayConfig.getMerchantId(),
                    new PrivateKeySigner(wxPayConfig.getMerchantSerialNumber(), merchantPrivateKey)),
            wxPayConfig.getPrivateKey().getBytes("utf-8"));
    

    你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

    待楼主反馈
    2022-11-24
    赞同
    回复 5
    • @@
      @@
      2022-11-25
      请 登录 后发表内容
      关闭

      新增或编辑超链接

      确认 取消
      关闭

      插入视频

      确认 取消
      发表
      搞定了搞定了

      你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

      待楼主反馈
      2022-11-25
      赞
      回复
      关闭

      请选择投诉理由

      • 广告内容
      • 违法违规
      • 恶意灌水内容
      • 其他
    • ㅤ
      ㅤ
      04-07 回复 @@
      请 登录 后发表内容
      关闭

      新增或编辑超链接

      确认 取消
      关闭

      插入视频

      确认 取消
      发表
      兄弟,你怎么解决的

      你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

      待楼主反馈
      04-07
      赞
      回复
      关闭

      请选择投诉理由

      • 广告内容
      • 违法违规
      • 恶意灌水内容
      • 其他
    • ㅤ
      ㅤ
      04-07 回复 ㅤ
      请 登录 后发表内容
      关闭

      新增或编辑超链接

      确认 取消
      关闭

      插入视频

      确认 取消
      发表
      好吧,我也解决了。。。。。。。。。。。。。

      你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

      待楼主反馈
      04-07
      赞
      回复
      关闭

      请选择投诉理由

      • 广告内容
      • 违法违规
      • 恶意灌水内容
      • 其他
    • 官方
      官方
      04-22 回复 ㅤ
      请 登录 后发表内容
      关闭

      新增或编辑超链接

      确认 取消
      关闭

      插入视频

      确认 取消
      发表
      怎么解决的,兄弟

      你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

      待楼主反馈
      04-22
      赞
      回复
      关闭

      请选择投诉理由

      • 广告内容
      • 违法违规
      • 恶意灌水内容
      • 其他
    • 官方
      官方
      04-22 回复 官方
      请 登录 后发表内容
      关闭

      新增或编辑超链接

      确认 取消
      关闭

      插入视频

      确认 取消
      发表
      我也解决了……,后面的兄弟注意把这个地方改了

      你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

      待楼主反馈
      04-22
      赞
      回复
      关闭

      请选择投诉理由

      • 广告内容
      • 违法违规
      • 恶意灌水内容
      • 其他
    关闭

    请选择投诉理由

    • 广告内容
    • 违法违规
    • 恶意灌水内容
    • 其他
  • Print
    Print
    2022-10-26
    请 登录 后发表内容
    关闭

    新增或编辑超链接

    确认 取消
    关闭

    插入视频

    确认 取消
    发表

    最后aes就是解密之后的报文了吗,就像jsapi下单之后的详细信息了吗

    你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

    待楼主反馈
    2022-10-26
    赞同
    回复 1
    • HOPE
      HOPE
      2022-10-27
      请 登录 后发表内容
      关闭

      新增或编辑超链接

      确认 取消
      关闭

      插入视频

      确认 取消
      发表
      是的

      你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

      待楼主反馈
      2022-10-27
      赞
      回复
      关闭

      请选择投诉理由

      • 广告内容
      • 违法违规
      • 恶意灌水内容
      • 其他
    关闭

    请选择投诉理由

    • 广告内容
    • 违法违规
    • 恶意灌水内容
    • 其他
  • Xiao_hu
    Xiao_hu
    2022-05-26
    请 登录 后发表内容
    关闭

    新增或编辑超链接

    确认 取消
    关闭

    插入视频

    确认 取消
    发表
      //加载平台证书,官方的sdk,s为
              PrivateKey merchantPrivateKey = PemUtil
                      .loadPrivateKey(new ByteArrayInputStream(s.getBytes("utf-8")));
    



    s是啥?

    你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

    待楼主反馈
    2022-05-26
    赞同
    回复 1
    • HOPE
      HOPE
      2022-05-27
      请 登录 后发表内容
      关闭

      新增或编辑超链接

      确认 取消
      关闭

      插入视频

      确认 取消
      发表
      商户API证书私钥内容

      你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。

      待楼主反馈
      2022-05-27
      赞
      回复
      关闭

      请选择投诉理由

      • 广告内容
      • 违法违规
      • 恶意灌水内容
      • 其他
    关闭

    请选择投诉理由

    • 广告内容
    • 违法违规
    • 恶意灌水内容
    • 其他
  • 无限大人
    无限大人
    2021-12-21
 
推荐文章
儒雅的豆芽  ·  C#实现一个最简单的HTTP服务器 - 小y
2 天前
长情的充电器  ·  MyBatis 3 | Mapper XML Files – mybatis
昨天
爱热闹的海龟  ·  入力検証時に表示される既定のメッセージの多言語対応を行う - ASP.NET Core - ソーサリーフォース
昨天
帅呆的茴香  ·  Asp.Net Core Authorize你不知道的那些事(源码解读) - Jlion
昨天
豪爽的西装  ·  RenderSettings | rhino3dm
9 小时前
任性的手电筒  ·  深圳组工在线
10 月前
腼腆的椅子  ·  江苏省人民政府 要闻关注 江苏公开第二轮中央生态环境保护督察整改方案
11 月前
侠义非凡的小蝌蚪  ·  2020年5月_大事记_云南省人民政府门户网站
1 年前
鼻子大的煎饼果子  ·  石景山区小升初公办校招生名单_石景山区优质公办初中_石景山区公办初中招生途径_石景山区新建校_通州九年一贯制/对口直升/集团校_北京小升初网
1 年前
叛逆的斑马  ·  极星3,专“割”有钱人_手机新浪网
1 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号