Java后台实现微信支付和微信退款
作者:桐桐桐汀灬 发布时间:2023-09-06 13:44:00
标签:Java,微信支付,微信退款
微信支付流程
都是我自己工作中开发的,亲测可用,不喜勿喷。
controller中我是这么写的,你们需要根据自己的业务需求改动。ResponseBean是我自己封装的,你们可以改成你们想要的形式。
/**
* 微信统一下单接口
* @return
*/
@RequestMapping(value = "/doUnifiedOrder", method = RequestMethod.POST)
public ResponseBean doUnifiedOrder(@RequestBody Map<String,Object> req) {
Map resultMap=new HashMap();
String openid = (String) req.get("openId");
WXPay wxpay =null;
try {
//初始化证书
myConfig.initCert();
wxpay= new WXPay(myConfig);
} catch (Exception e) {
e.printStackTrace();
}
//生成的随机字符串
String nonce_str = WXPayUtil.generateNonceStr();
//获取客户端的ip地址
//获取本机的ip地址
InetAddress addr = null;
try {
addr = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
//支付金额,需要转成字符串类型,否则后面的签名会失败
String payOutMoney = WxMoney.changeY2F(String.valueOf(req.get("money")));
String tradeName = (String) req.get("tradeName");
if(tradeName!=null&&tradeName.length()>0){
}else{
tradeName = "课程支付";
}
String body = tradeName;
//商户订单号
String out_trade_no= WXPayUtil.generateNonceStr();
//统一下单接口参数
HashMap<String, String> data = new HashMap<String, String>();
data.put("appid", 你的appid);
data.put("mch_id", 商户id);
data.put("nonce_str", nonce_str);
data.put("body", body);
data.put("out_trade_no",out_trade_no);
data.put("total_fee", payOutMoney);
data.put("spbill_create_ip", "127.0.0.1");
data.put("notify_url", 回调地址);
data.put("trade_type","JSAPI");
data.put("openid", openid);
try {
Map<String, String> rMap = wxpay.unifiedOrder(data);
String return_code = (String) rMap.get("return_code");
String result_code = (String) rMap.get("result_code");
String nonceStr = WXPayUtil.generateNonceStr();
resultMap.put("nonceStr", nonceStr);
Long timeStamp = System.currentTimeMillis() / 1000;
if ("SUCCESS".equals(return_code) && return_code.equals(result_code)) {
String prepayid = rMap.get("prepay_id");
resultMap.put("package", "prepay_id="+prepayid);
resultMap.put("signType", "MD5");
//这边要将返回的时间戳转化成字符串,不然小程序端调用wx.requestPayment方法会报签名错误
resultMap.put("timeStamp", timeStamp + "");
//再次签名,这个签名用于小程序端调用wx.requesetPayment方法
resultMap.put("appId",myConfig.getAppID());
String sign = WXPayUtil.generateSignature(resultMap, myConfig.getKey());
resultMap.put("paySign", sign);
resultMap.put("out_trade_no",out_trade_no);
ResponseBean responseBean = new ResponseBean(HttpStatus.OK.value(),"微信支付",resultMap);
return responseBean;
}else{
ResponseBean responseBean = new ResponseBean(HttpStatus.OK.value(),"微信支付失败","微信支付失败");
return responseBean;
}
} catch (Exception e) {
ResponseBean responseBean = new ResponseBean(HttpStatus.OK.value(),"微信支付失败","微信支付失败");
e.printStackTrace();
return responseBean;
}
}
微信退款代码(需要传退款的订单id)
public ResponseBean refund(Map<String, Object> req) {
Map resultMap=new HashMap();
String buyId = (String) req.get("buyId");
WXPay wxpay =null;
try {
myConfig.initCert();//初始化证书
wxpay= new WXPay(myConfig);
} catch (Exception e) {
e.printStackTrace();
}
//生成的随机字符串
String nonce_str = WXPayUtil.generateNonceStr();
//获取客户端的ip地址
//获取本机的ip地址
InetAddress addr = null;
try {
addr = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
//支付金额,需要转成字符串类型,否则后面的签名会失败
// int total_fee= (int) req.get("money");
String payOutMoney = WxMoney.changeY2F(String.valueOf(req.get("money")));
// String body = (String) req.get("z");
//商户订单号
String out_trade_no= WXPayUtil.generateNonceStr();
//统一下单接口参数
HashMap<String, String> data = new HashMap<String, String>();
try {
data.put("appid", myConfig.getAppID());
data.put("mch_id", myConfig.getMchID());
data.put("nonce_str", nonce_str);
data.put("sign_type", "MD5");
data.put("out_trade_no",buyId);//微信订单号
data.put("out_refund_no", out_trade_no);//商户退款单号
data.put("total_fee",payOutMoney);//支付金额,微信支付提交的金额是不能带小数点的,且是以分为单位,这边需要转成字符串类型,否则后面的签名会失败
data.put("refund_fee",payOutMoney);//退款总金额,订单总金额,单位为分,只能为整数
//MD5运算生成签名,这里是第一次签名,用于调用统一下单接口
String sign = WXPayUtil.generateSignature(data, myConfig.getKey());
data.put("sign", sign);
Map<String, String> rMap = wxpay.refund(data);
String return_code = (String) rMap.get("return_code");
String result_code = (String) rMap.get("result_code");
Long timeStamp = System.currentTimeMillis() / 1000;
if ("SUCCESS".equals(return_code) && return_code.equals(result_code)) {
ResponseBean responseBean = new ResponseBean(HttpStatus.OK.value(),"微信退款成功",rMap);
return responseBean;
}else{
ResponseBean responseBean = new ResponseBean(HttpStatus.OK.value(),"微信退款失败","微信支付失败");
return responseBean;
}
} catch (Exception e) {
ResponseBean responseBean = new ResponseBean(HttpStatus.OK.value(),"微信退款失败","微信支付失败");
e.printStackTrace();
return responseBean;
}
}
需要用到的工具类
然后在MyConfig中配置一下你们的小程序参数就行了,如果需要添加退款功能必须配置商户证书(对应在你项目中的位置)。不需要的话就把initCert方法去掉。
public class MyConfig extends WXPayConfig {
@Value("${res.imgPath}")
public String imgPath;
private byte[] certData;
@Override
public String getAppID() {
return "你的小程序id";
}
@Override
public String getMchID() {
return "商户id";
}
@Override
public String getKey() {
return "商户秘钥";
}
@Override
public InputStream getCertStream() {
ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
return certBis;
}
@Override
public int getHttpConnectTimeoutMs() {
return 8000;
}
@Override
public int getHttpReadTimeoutMs() {
return 10000;
}
@Override
IWXPayDomain getWXPayDomain() {
return new IWXPayDomain() {
@Override
public void report(String domain, long elapsedTimeMillis, Exception ex) {
}
@Override
public DomainInfo getDomain(WXPayConfig config) {
return new DomainInfo("api.mch.weixin.qq.com", false);
}
};
}
@Override
public void initCert() throws Exception {
String certPath = this.imgPath+"/upload/cert/"+"apiclient_cert.p12";//从微信商户平台下载的安全证书存放的目录
System.out.println(certPath);
File file = new File(certPath);
InputStream certStream = new FileInputStream(file);
this.certData = new byte[(int) file.length()];
certStream.read(this.certData);
certStream.close();
}
}
来源:https://blog.csdn.net/weixin_44045144/article/details/104884298
0
投稿
猜你喜欢
- Android EditText限制输入字符类型的方法总结前言:最近的项目上需要限制EditText输入字符的类型,就把可以实现这个功能的方
- AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Map
- Stripe支付首页需要引用Stripe.net框架,我引用的是22.8.0版本,注意.NETFramework的版本为4.5,同时需要引用
- 场景我们团队现在面临着多端数据接口对接的问题,为了解决这个问题我们定义了接口对接的规范,前端(安卓,Ios,web前端)和后端进行了数据的格
- 我们的spring cloud微服务一般是打成jar包发布的,Linux下启动jar包和windows下一样,都是java -jar 包名,
- 我们写的主类中的main()方法是如何被Java虚拟机调用到的?在Java类中的一些方法会被由C/C++编写的HotSpot虚拟机的C/C+
- 前言${} 和 #{} 都是 MyBatis 中用来替换参数的,它们都可以将用户传递过来的参数,替换到 MyBatis 最终生成的
- 1.创建简单的XML文件为了便于测试,我们首先创建控制台应用程序,项目命名为CreateXml,Program.cs代码如下:using S
- JavaMail API中定义了一个java.mail.Transport类,它专门用于执行邮件发送任务,这个类的实例对象封装了某种邮件发送
- 一. * 搭建及配置1 . * 简介 * 是架设在局域网的一种特殊的远程仓库,目的是代理远程仓库及部署第三方构件。有了 * 之后,当 Maven
- using System;using System.Collections.Generic;using System.IO;using Sy
- 1.最近的项目中,有一个Activity用到Fragment+ViewPager,其中一个fragment中实现了视频播放的功能,包含有Su
- Flink中设计了用户自定义函数体系(User Defined Function,UDF),开发人员实现业务逻辑就是开发UDF。一、环境对象
- @ApiModel使用场景在实体类上边使用,标记类时swagger的解析类概述提供有关swagger模型的其它信息,类将在操作中用作类型时自
- 本文实例为大家分享了java实现随机数生成器的具体代码,供大家参考,具体内容如下自己编的随机数生成器,比较简陋,功能也单一,当作练手。App
- 之前在介绍使用JdbcTemplate和Spring-data-jpa时,都使用了单数据源。在单数据源的情况下,Spring Boot的配置
- 内部类1. 内部类简介(1) 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。(2) 内部类成员可以
- 问题描述Feign 在请求时是不会将 request 的请求头带着请求的,导致假如 Feign 调用的接口需要请求头的信息,比如当前用户的
- 前言在上一章节Spring和Mybatis整合的原理详解中有写到Spring和MyBatis整合时用到的Bean扫描是Spring本身提供的
- 接口等幂性通俗的来说就是同一时间内,发起多次请求只有一次请求成功;其目的时防止多次提交,数据重复入库,表单验证网络延迟重复提交等问题。比如: