4.微信支付
1.付款码支付 用户展示微信钱包的二维码给商户系统扫描,然后用户自动支付跳出金额
2.Native支付(用户扫商户系统按微信支付协议的二维码,比较复杂)(适用于PC网站支付,实体店单品美宜佳...)
二维码是微信的url,微信扫一扫就是一个浏览器,得到url可以跳转
3.JSAPI 商户通过调用jsapi调取微信支付模块完成支付(灵活好用)(在微信扫码或点击链接打开支付,客户扫商户)
1.用户公众号支付
2.用户在朋友圈,聊天窗口 点击跳转商家页面支付
3.自动跳转微信完成支付
4.APP支付 手机上装app调用微信支付模块
5.H5支付 区分JSAPI 在任意一款浏览器都可以(灵活,)
6.刷脸支付 需要在注册微信支付的设备上用
6.开通jsapi,需要公众平台和微信支付关联(公众平台导航栏有个微信支付,微信支付的产品中心有个关联)
0.微信支付安全中心设置api秘钥(随机密码生成器生成32位)
1.api证书v3版本需要 下载证书工具 请求串到微信支付,复制微信支付串到工具生成证书
7.java代码
0.加微信的依赖
1.需要APPID标识哪个用户调用,api秘钥和AppScret密码和备案一个网站
//要替换的变量的授权码
String.format("xxx%s,%s",appId,wxAuthCode)
//重定向到url
return "redirect:"+url;
2.//授权后给微信回调,下单必须申请openid!!!
//ngrok natapp frp lanproxy spike 花生壳实现内网穿透
//项目使用natapp工具,安装微信客户端
3.用户用微信扫码,调controller打开h5网页(微信sdk填参数自动生成),有js脚本
//wxpay对应的是template的视图名称 没有集成freemake,要将html名称改为wxpay.ftl
return new ModelAndView("wxpay",jsapiPayParam)
8.加密方式(2者结合)
对称加密:(秘钥会共享,被得到会破解)(秘钥是同一个) 常用AES算法(秘钥加密明文,传输后也秘钥加密明文后解密)
非对称加密(慢)(秘钥不是同一个) 公钥加密 私钥解密(加密信息) 两个不一样 公钥解密 私钥加密(身份认证) RSA
摘要算法digest(确保传输过程信息不被改变,生成一个唯一值)(只能加密不能解密,破解只能枚举,放散性改动一定全部改变,抗碰撞性原文不同计算后的摘要也要不同)
MD5 SHA1 SHA2(SHA224 256 384)
流程是使用摘要后这个私钥加密 然后使用公钥解密对比原来的摘要,确定数据不被篡改
数字证书(ca Certificate Authority 证书认证机构发) 以免公钥被黑客伪造,得到 我自己的公钥 去给自己解密
9.使用 需要到微信支付的证书介绍使用api接口得到平台证书,代表平台也加密了(得到公钥)以免过期
//项目 swagger有用的注解 在controller加 @Api(tags="商品管理")
//方法上加@ApiOperation("测试接口") get post 点击得到所有数据 lombok已经被springboot管理,不用写版本号
//lombok idea最左边有structure可以看到生成后的代码
//在yml 修改jackson时区数据显示方式
//在Tool wins的database-->data source--->mysql-->写名字 --->all schema
//打开了新窗口 复制sql语句
// mybatis plus在实体类加数据库的表名 @TableName("xxx")
@TabledId(value="id",type=IdType.AUTO) //在实体类指定主键自动增长
mapper extends BaseMapper<xx实体类>
//同时提供了service的方法 serviceImpl<xxMapper,OrderInfo> implements OrderInfoService
//可以在里面有分页和基本增删改查
//在config文件夹写个MybatisPlusConfig方法 扫描 mapper.java文件
//在yml加mp的配置 使xml被编译
//安装前端插件 vetur vuehelper
//安装vue调试工具 压缩包到谷歌的更多工具-->拓展查询 开发工具-->加载
---f12 -->vue选项卡
//springboot -和驼峰名字在配置文件一一对应
// !!!swagger 只需要有api就可以测试!!! 方法加是为了注释
//导入依赖,project structure -->customize spring boot 增加配置文件,可以按住ctrl点击跳转到 PropertiesSources配置文件
//加载商户.pem私钥文件
//在线得到签名证书
//回调通知 微信会自动发信息到我们系统,可能失败,需要主动调用微信查询订单的状态
//@Bean可以直接注入
//后台可以拿到响应的url,给前端展示二维码,然后后端使用定时任务不断检查 用户扫码状态
//在yml文件写 可以把我们引入依赖的日志也打印出来
logging:
level:
root: debug
10.发送支付请求的过程
接口规则
1.构造签名串(有固定格式)
2.计算签名值, 先sha256签名,在进行base64编码(摘要算法)
3.设置http头
Authorization: 认证类型,签名信息 //加密方式,我们的签名(验证权限的东西)的信息
11.远程异步请求,怎么处理?
需要远程下载平台证书(因为微信支付平台证书需要不断更新的)
12.logslf4可以根据你在代码生成 指定信息的日志,比如debug日志 info日志
logging:
level:
root: info
//代码写 ,info可以看代码的大致执行情况, debug可以调试错误()
log.info("aaa");
//还可以替换{}占位符里面的内容
log.info("支付通知的id===>{}",bodyMap.get("id"));
- mp的 baseMapper 就是相当于当前mapper,会动态改变的
//mp的查询对象, 防止用户重复提交订单,重复插入订单信息
QueryWrapper<OrderInfo> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("product_id",productId);
queryWrapper.eq("order_status",OrderStatus,NOTPAY.getType());//条件查询
OrderInfo orderInfo=baseMapper.selectOne(queryWrapper);//查询一条数据
return orderInfo
//点击了支付,第一次点击创建订单号,第二次点击保存 url二维码返回给前端
//倒序排序
QueryWrapper<OrderInfo> queryWrapper=new QueryWrapper<OrderInfo>().orderByDesc("create_time");
baseMapper.selectList(queryWrapper);
//更新数据
queryWrapper.eq("order_no",orderNo)
new OrderInfo();
baseMapper.update(orderInfo,queryWrapper);
14.使用内网穿透,微信服务器给我发请求(后面我使用frps了好好用)
ngrok.com //我们使用https
//注册 执行访问令牌命令
- 如果我们的格式不符合规范,微信不断通知我们结果
1.如果们应答超过5秒,微信也会认为失败,不断发请求
2.更新订单状态,增加订单详细信息记录,查账
3.后期对账的时候需要用 transaction_id
4.交易状态可以看状态
微信接口给我们 重复通知,导致用户积分成倍增加,要先检查订单状态,不用重复处理
return;
并发也会重复调用,在controller有个睡眠,在service也有一个,导致并发重复插入订单数据,因为订单状态,在同一时间是未支付的状态,也是会导致日志重复增加的问题
//juc必须加锁,使用尝试获取锁 成功返回true 失败立即返回false,不必像synchronize一直等待锁的释放 不浪费表情-_-
private final ReentrantLock lock=new ReentrantLock();
if(lock.tryLock()){
try{
//业务逻辑
}finally{
//释放锁
lock.unlock();
}
}
6.接口调用的幂等性:无论接口调用多少次,产生的结果是一致的
payer_total实际是double类型
//步骤, 我们发起请求(参数,商户id,..支付数据)摘要 公钥加密--->微信验签私钥解密
// 微信调用我们接口, --->--->验签(摘要算法)(数据完整性) --->解密--->明文
//
16.前端怎么知道我们的支付状态
1.写后端查订单状态接口
2.前端使用定时器调用接口 跳转到支付成功页面
this.timer=setInterval(()=>{
this.queryOrderStatus();
},3000);
//如果状态码是0,清除定时器
clearInterval(this.timer);
17.用户取消订单和主动取消订单
//调用微信支付的关单接口
//枚举类的url有个%s占位符 http:xxx/%s ,需要我们去替换
String url =String.format(WxApiType.CLOSE_ORDER_BY_NO.getType(),orderNo);
url =WxPayConfig.getDomain().concat(url);
//创建远程请求
HttpPost httpPost=new HttpPost(url);
new Gson();
Map<String,String> map =new HashMap();
map.put("mchid",wxPayConfig.getMchId);
//更新订单状态
gson.toJson(map);
log.info("请求参数 ===> {}",map);
//请求参数设置请求对象中,成功返回204,没有返回数据
//完成签名并执行请求
CloseableHttpResponse response = wxPayClient.execute(httpPost);
18.如果微信订单接口5分钟都没有返回处理结果,我们主动调用查单接口,查看订单状态(定时任务)
//spring的默认定时任务功能spring Task
//启动类加上@EnableScheduling
//在一个@Component的方法中写
//日和周不能同时写,必须要另外一个为?
//秒分时日月周 *每秒都执行 1-3 第一秒执行,第三秒结束
// 0/3从第0秒开始,每隔3秒执行一次
// 1,2,3 在指定的第1,2,3秒执行
// ?不指定
@Scheduled(cron="0/30 ****?")
public void task1(){
//从第0秒开始,每隔30秒执行一次.查询超过5分钟.且未支付的订单
}
//得到超过minutes分钟的未支付的订单
Instant instant=Instant.now().minus(Duration.ofMinutes(minutes));
QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("order_status",OrderStatus.NOPAY.getType());
queryWrapper.le("create_time",instant);//小于这个时间的--->就是之前的
baseMapper.selectList(queryWrapper);
//查询微信订单状态,未支付 则关闭订单,有订单更新订单支付
19.退款
1.微信支付部分退款
20.退款结果通知
21.下载账单(xls文件)用来对账 ,当天的账单不能查??? 微信会返回账单下载地址url需要参数继续发请求,下载功能通过前端的代码,后端提供数据
22.apiv2和v3区别 v3更安全,v2有一些特殊功能如付款码但是只支持post请求使用xml对象
23.整合v2到v3