微信支付模式二java
这个星期写了下微信支付模式二,在这里进行下整理
微信支付官方文档
1. 需要的配置..具体看下面的链接.
https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=3_1
2. 熟悉微信的支付流程(模式二)
https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5
3.将下面的配置填好,我是写在yml里面.第一个没用到,说是公众号那里用到了,可以不用
.
4.下载微信里面的sdk,然后全部放入项目里面
https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1
下面就是具体的代码...微信支付模式二是先将金额订单号等一些参数放入二维码中,这个二维码只有2个小时,然后顾客扫码支付
需要的jar包
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jdom/jdom -->
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom</artifactId>
<version>1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/xml-apis/xml-apis -->
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
5.先是写二维码的
util ---2个
/**
* @ClassName: QRCodeUtil
* @Description: 二维码工具类
*/
public class QRCodeUtil {
/**
* 生成base64二维码
*
* @param content
* @return
* @throws Exception
*/
public static String createQrCode(String content) throws Exception {
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, 400, 400, hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
ImageIO.write(image, "JPG", out);
return Base64.encodeBase64String(out.toByteArray());
}
}
}
public class CommonUtil {
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
try {
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod);
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 当outputStr不为null时向输出流写数据
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
return buffer.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
controller ----这里可以直接传参数,订单号,类型
serviceImpl
@Override
public ApiResult toPay(String orderUserId, String payType) {
OrderUserInfoDto orderUserInfoDto = orderUserInfoService.getByPk(orderUserId);
if (Checker.BeNull(orderUserInfoDto)) {
return ApiResult.result(ApiResult.defaultErrorCode, "未知的订单号");
}
if (!"0".equals(orderUserInfoDto.getPayStatus())) {
return ApiResult.result(ApiResult.defaultErrorCode, "未知的支付状态");
}
if(!"3".equals(orderUserInfoDto.getStatus())){
return ApiResult.result(ApiResult.defaultErrorCode,"未知的订单状态");
}
// 1为微信支付
if ("1".equals(payType)) {
SortedMap<String, String> parameters = new TreeMap<String, String>();
// 公众账号ID-------appId
parameters.put("appid", weChatConfig.getWxAppId());
// 商户号---------mch_id
parameters.put("mch_id", weChatConfig.getWxMchId());
// 随机字符串------nonce_str
parameters.put("nonce_str", WXPayUtil.generateNonceStr());
// 商品描述-------body
parameters.put("body", weChatConfig.getBody());
// 商户订单号------out_trade_no
parameters.put("out_trade_no", orderUserId);
// 标价币种-------fee_type(默认为人民币)
parameters.put("fee_type", "CNY");
// 标价金额-------total_fee(默认为分)
BigDecimal transValue = new BigDecimal("100");
// 计算微信的总金额乘以100
BigDecimal bTotalPrice = orderUserInfoDto.getTotalPrice().multiply(transValue);
int totalFee = bTotalPrice.intValue();
parameters.put("total_fee", String.valueOf(totalFee));
// 通知地址-------notify_url(回调地址)
parameters.put("notify_url", weChatConfig.getNotifyUrl());
// 交易类型-----trade_type
parameters.put("trade_type", "NATIVE");
// 签名-----------sign
String generateSignature = null;
try {
generateSignature = WXPayUtil.generateSignature(parameters, weChatConfig.getWxApiKey(),
WXPayConstants.SignType.MD5);
} catch (Exception e) {
e.printStackTrace();
}
parameters.put("sign", generateSignature);
String generateSignedXml = null;
try {
generateSignedXml = WXPayUtil.generateSignedXml(parameters, weChatConfig.getWxApiKey());
} catch (Exception e) {
e.printStackTrace();
}
log.info("二维码信息------" + generateSignedXml);
String result = CommonUtil.httpsRequest(weChatConfig.getWxPayUnifiedorderUrl(), "POST", generateSignedXml);
Map<String, String> map;
try {
map = WXPayUtil.xmlToMap(result);
String returnCode = map.get("return_code");
String resultCode = map.get("result_code");
if (returnCode.equalsIgnoreCase("SUCCESS") && resultCode.equalsIgnoreCase("SUCCESS")) {
String content = map.get("code_url");
String imgs = QRCodeUtil.createQrCode(content);
return ApiResult.result("data:image/jpeg;base64," + imgs);
} else {
return ApiResult.result(ApiResult.defaultErrorCode, "微信签名错误");
}
} catch (Exception e) {
e.printStackTrace();
}
}
return ApiResult.result(ApiResult.defaultErrorCode, "未知错误");
}
6,支付回调-----就是二维码的那个回调地址,如果是本地测试的话,可能下载个花生壳将本地的地址映射出去
controller
serviceImpl --->这里主要注意就是第一次回调成功的话,要把正确的信息返回给微信,不然微信会在那几个时间一直回调,这个回调就会一直改状态
public String weChatNotify(HttpServletRequest request, HttpServletResponse response) {
// 读取参数
InputStream inputStream;
StringBuffer sb = new StringBuffer();
inputStream = request.getInputStream();
String s;
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
while ((s = in.readLine()) != null) {
sb.append(s);
}
in.close();
inputStream.close();
// 解析xml成map
Map<String, String> map = WXPayUtil.xmlToMap(sb.toString());
log.info("支付回调---" + map.toString());
String res = "OK";
String resXml = "<xml>" + "<return_code><![CDATA["+map.get("return_code").toString()+"]]></return_code>"
+ "<return_msg><![CDATA["+res+"]]></return_msg>" + "</xml>";
// 判断签名是否正确
if (WXPayUtil.isSignatureValid(map, weChatConfig.getWxApiKey())) {
if ("SUCCESS".equals(map.get("return_code").toString())) {
// 用户订单号
String orderUserId = (String) map.get("out_trade_no");
// 微信支付订单号
String payOrderId = (String) map.get("transaction_id");
// 支付时间
String endTime = (String) map.get("time_end");
// 支付金额
BigDecimal total_fee = new BigDecimal(map.get("total_fee").toString());
/**
* 1,判断是否有这个订单号 2,判断支付金额与用于订单表的金额是否一致 3,修改支付状态,并修改商户的状态,
*/
log.info("用户订单id--------"+orderUserId);
OrderUserInfoDto orderUserInfoDto = orderUserInfoService.getByPk(orderUserId);
if (Checker.BeNull(orderUserInfoDto)) {
return "未知的订单号";
}
if (!"0".equals(orderUserInfoDto.getPayStatus())) {
return "未知的支付状态";
}
if (!"3".equals(orderUserInfoDto.getStatus())) {
return "未知的订单状态";
}
if (total_fee.compareTo(orderUserInfoDto.getTotalPrice().multiply(new BigDecimal("100"))) != 0) {
return "支付金额与用户订单金额不一致";
}
// 用户订单表的修改
OrderUserInfoDto orderUserInfoDto1 = new OrderUserInfoDto();
orderUserInfoDto1.setId(orderUserId);
orderUserInfoDto1.setStatus("4");
orderUserInfoDto1.setPayStatus("1");
orderUserInfoDto1.setPayType("1");
orderUserInfoDto1.setPaySerial(payOrderId);
log.info("----------------时间---"+endTime);
orderUserInfoDto1.setPayTime(dateTime(endTime));
orderUserInfoService.updateByPk(orderUserInfoDto1);
// 商户订单表的修改
List<OrderMerchantInfoDto> orderMerchantInfoDtoList = orderMerchantInfoService
.listByField("order_user_info_id", orderUserId);
for (OrderMerchantInfoDto merchantInfoDto : orderMerchantInfoDtoList) {
if ("3".equals(merchantInfoDto.getStatus())) {
String id = merchantInfoDto.getId();
OrderMerchantInfoDto orderMerchantInfoDto = new OrderMerchantInfoDto();
orderMerchantInfoDto.setId(id);
orderMerchantInfoDto.setStatus("4");
orderMerchantInfoDto.setPayStatus("1");
orderMerchantInfoDto.setPayTime(dateTime(endTime));
orderMerchantInfoService.updateByPk(orderMerchantInfoDto);
}
}
log.info(resXml);
return resXml;
} else {
return "错误的签名";
}
}
return "未知错误";
}
7,客户支付成功了,但是状态没改,可以写个定时任务,查询当天未支付的订单是否支付,我这里只写了通过订单号和类型查询单个的是否支付
controller
serviceImpl
@Override
public ApiResult weChatNotifyDto(String orderUserId, String payType) {
/**
* 1,数据库进行查询,如果显示已支付则直接返回成功
* 2,未支付,调用微信接口
*/
OrderUserInfoDto orderUserInfoDto = orderUserInfoService.getByPk(orderUserId);
if("1".equals(orderUserInfoDto.getPayStatus())){
return ApiResult.result("支付已完成");
}
Map<String,String> data = new HashMap<>();
data.put("appid", weChatConfig.getWxAppId());
data.put("mch_id", weChatConfig.getWxMchId());
data.put("nonce_str", WXPayUtil.generateNonceStr());
data.put("out_trade_no", orderUserId);
// 签名-----------sign
String generateSignature = null;
try {
generateSignature = WXPayUtil.generateSignature(data, weChatConfig.getWxApiKey(),
WXPayConstants.SignType.MD5);
} catch (Exception e) {
e.printStackTrace();
}
data.put("sign", generateSignature);
Map<String, String> result = null;
try {
result = wxPay.orderQuery(data);
} catch (Exception e) {
e.printStackTrace();
}
// 如果用户已支付
if("SUCCESS".equals(result.get("return_code")) && "SUCCESS".equals(result.get("trade_state"))){
//修改状态
// 微信支付订单号
String payOrderId = result.get("transaction_id");
// 支付时间
String endTime = result.get("time_end");
// 用户订单表的修改
OrderUserInfoDto orderUserInfoDto1 = new OrderUserInfoDto();
orderUserInfoDto1.setId(orderUserId);
orderUserInfoDto1.setStatus("4");
orderUserInfoDto1.setPayStatus("1");
orderUserInfoDto1.setPayType("1");
orderUserInfoDto1.setPaySerial(payOrderId);
orderUserInfoDto1.setPayTime(dateTime(endTime));
orderUserInfoService.updateByPk(orderUserInfoDto1);
// 商户订单表的修改
List<OrderMerchantInfoDto> orderMerchantInfoDtoList = orderMerchantInfoService
.listByField("order_user_info_id", orderUserId);
for (OrderMerchantInfoDto merchantInfoDto : orderMerchantInfoDtoList) {
if ("3".equals(merchantInfoDto.getStatus())) {
String id = merchantInfoDto.getId();
OrderMerchantInfoDto orderMerchantInfoDto = new OrderMerchantInfoDto();
orderMerchantInfoDto.setId(id);
orderMerchantInfoDto.setStatus("4");
orderMerchantInfoDto.setPayStatus("1");
orderMerchantInfoDto.setPayTime(dateTime(endTime));
orderMerchantInfoService.updateByPk(orderMerchantInfoDto);
}
}
return ApiResult.result("支付已完成");
}
return ApiResult.result(ApiResult.defaultErrorCode, "订单未支付");
}
暂时先这样,有时间再补充
微信支付模式二java的更多相关文章
- JAVA微信扫码支付模式二功能实现完整例子
概述 本例子实现微信扫码支付模式二的支付功能,应用场景是,web网站微信扫码支付.实现从点击付费按钮.到弹出二维码.到用户用手机微信扫码支付.到手机上用户付费成功.web网页再自动调整到支付成功后的页 ...
- Java之微信支付(扫码支付模式二)案例实战
摘要:最近的一个项目中涉及到了支付业务,其中用到了微信支付和支付宝支付,在做的过程中也遇到些问题,所以现在总结梳理一下,分享给有需要的人,也为自己以后回顾留个思路. 一:微信支付接入准备工作: 首先, ...
- 微信公众号 扫码支付 模式二 demo
扫码支付 本文附有代码,在下方,如果不熟悉场景的可以看看下面的场景介绍 场景介绍 官网介绍地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?ch ...
- 微信支付Native扫码支付模式二之CodeIgniter集成篇
CI:3.0.5 微信支付API类库来自:https://github.com/zhangv/wechat-pay 请先看一眼官方场景及支付时序图:https://pay.weixin.qq.com/ ...
- C# 微信扫码支付API (微信扫码支付模式二)
一.SDK下载地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1,下载.NET C#版本: 二.微信相关设置:(微信扫码 ...
- PHP微信支付开发之扫描支付(模式二)后如何回调
其实在写这篇文章的时候感觉自己已经落伍了,不过笔者在百度上搜索"微信支付开发之扫描支付(模式二)后如何回调"寻找答案时,发现依旧有很多朋友没有解决这个问题,所以就把自己的解决思路分 ...
- .NET MVC结构框架下的微信扫码支付模式二 API接口开发测试
直接上干货 ,我们的宗旨就是为人民服务.授人以鱼不如授人以渔.不吹毛求疵.不浮夸.不虚伪.不忽悠.一切都是为了社会共同进步,繁荣昌盛,小程序猿.大程序猿.老程序猿还是嫩程序猿,希望这个社会不要太急功近 ...
- .NET微信扫码支付模式二API接口开发测试
主要实现微信扫码支付,官网的SDKdemo 就不要使用 一直不能调试通过的,还是自己按照API接口文档一步一步来实现,吐槽下微信一点责任感都木有,能不能demo搞个正常的吗,不要坑惨了一大群码农们有点 ...
- thinkphp5.0 微信扫码支付模式二
仅供个人参考,方便大家. 一.1)https://pay.weixin.qq.com/index.php/core/home/login 复制此地址 打开微信商户平台. 2)下载安全操作证书(最好在 ...
- 【weixin】微信支付---Native支付模式二(PC端支付大多采用此模式)
[模式二]:商户后台系统调用微信支付[统一下单API]生成预付交易,将接口返回的链接生成二维码,用户扫码后输入密码完成支付交易.注意:该模式的预付单有效期为2小时,过期后无法支付 模式二与模式一相比, ...
随机推荐
- C#Autofac依赖注入批量注入 (目前版本.netcore3.0)
上一文:C#依赖注入一看就会系列 链接:C#依赖注入(直白明了)讲解 一看就会系列 - 22222220 - 博客园 (cnblogs.com) 上一次我们知道了 为什么要依赖注入,这次我们就用使用人 ...
- 使用 LoRA 进行 Stable Diffusion 的高效参数微调
LoRA: Low-Rank Adaptation of Large Language Models 是微软研究员引入的一项新技术,主要用于处理大模型微调的问题.目前超过数十亿以上参数的具有强能力的大 ...
- 借教室NOIP2012
题目: 这道题目就是差分加二分答案. 先看为什么能差分,因为题目中的从s[j]借到t[j]就相当于对一个区间进行操作:再看为什么能二分,废话有单调性啊因为可以借n个教室那也可以借n个以下的教室,相反如 ...
- 力扣每日一题2023.1.19---2299. 强密码检验器 II
如果一个密码满足以下所有条件,我们称它是一个 强 密码: 它有至少 8 个字符. 至少包含 一个小写英文 字母. 至少包含 一个大写英文 字母. 至少包含 一个数字 . ...
- Linux 安装 CentOS7
1.linux 下载 http://mirrors.aliyun.com/centos/7/isos/x86_64/ centos-7-isos-x86_64安装包下载_开源镜像站-阿里云 (aliy ...
- javaEE(网络编程、TCP、线程池优化)
网络编程 Client-Server(CS) Browser/Server(BS) 1.客户端--服务端 安装客户端 更新. 依赖PC 2.浏览器和服务端 分布式 兼容性 一站开发 网络通信: UDP ...
- JZOJ 3242. Spacing
\(\text{Analysis}\) 最大值最小很容易想到二分答案 然后用 \(dp\) 检查 设 \(f_i\) 表示当前行最后一个为 \(i\) 时最优情况最大空格数是否小于 \(mid\) 若 ...
- IP转换
IP转换 目录 IP转换 1 127.1 ? 2 IPv4两段点分十进制表示 3 IPv4一段十进制表示 4 IPv4地址有效地变换形式 5 IP地址进制转换网站 6 参考博客 1 127.1 ? 首 ...
- 置顶TOP
HTML <a href="javascript:void(0)" class="go-top" @click="goTop"> ...
- 化学式latex语法
$2 CO_2 \stackrel{光}{\underset{\text{催化剂}}{\longrightarrow}}2 Fe + 3 CO_2$ $\ce{CO2}$ $\ce{CU2+}$ $\ ...