admin管理员组文章数量:1559090
微信支付开通支付方法在这里可以参考一下:申请开通微信支付教程_个人怎么申请微信支付_郑鹏川的博客-csdn博客
因为微信支付回调需要一个外网可访问的地址,我本地调试是采用的内网穿透的方式进行调试的。
cpolar是一款内网穿透工具,它支持http/https/tcp协议,不限制流量,操作简单,无需公网ip,也无需路由器,可以轻松把服务暴露到公网访问。
cpolar九游会真人第一品牌官网:cpolar - 安全的内网穿透工具
1 下载安装cpolar内网穿透
访问cpolar九游会真人第一品牌官网,注册一个账号,并下载安装cpolar客户端。详细可以参考文档教程进行下载安装。
2 创建隧道
cpolar安装成功后,我们在浏览器上访问本地9200端口,登录cpolar的web ui界面:http://localhost:9200。
点击左侧仪表盘的隧道管理——创建隧道,由于tomcat中配置的是82端口,因此我们要来创建一条http隧道,指向82端口:
隧道名称:可自定义,注意不要与已有隧道名称重复
协议:http协议
本地地址:82
域名类型:免费选择随机域名
地区:选择china top
点击左侧仪表盘的状态——在线隧道列表,可以看到刚刚创建的隧道已经有生成了相应的公网地址,一个http协议,一个https协议(免去配置ssl证书的繁琐步骤),将其复制想下来
接下来我们就直接上代码了:
一、引入官方提供的pom依赖
com.github.wechatpay-apiv3
wechatpay-apache-httpclient
0.4.2
二、配置微信支付必要的参数
weixin:
appid: # appid
mch-serial-no: # 证书序列号
private-key-path: apiclient_key.pem # 证书路径 我这边保存在resource文件夹下读取文件时通过classpathresource去读取的
mch-id: # 商户号
key: # api秘钥
domain: https://api.mch.weixin.qq # 微信服务器地址
notify-domain: http://303fe2d4.r5.cpolar.top/v3/wechat/callback # 回调,自己的回调地址需要外网可访问
三、编写微信支付配置类
import com.qzmon.exception.commonexception;
import com.wechat.pay.contrib.apache.httpclient.wechatpayhttpclientbuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.privatekeysigner;
import com.wechat.pay.contrib.apache.httpclient.auth.verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.wechatpay2credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.wechatpay2validator;
import com.wechat.pay.contrib.apache.httpclient.cert.certificatesmanager;
import com.wechat.pay.contrib.apache.httpclient.exception.httpcodeexception;
import com.wechat.pay.contrib.apache.httpclient.exception.notfoundexception;
import com.wechat.pay.contrib.apache.httpclient.util.pemutil;
import lombok.data;
import org.apache.http.impl.client.closeablehttpclient;
import org.springframework.boot.context.properties.configurationproperties;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.context.annotation.propertysource;
import org.springframework.core.io.classpathresource;
import java.io.ioexception;
import java.nio.charset.standardcharsets;
import java.security.generalsecurityexception;
import java.security.privatekey;
/**
* @author lihao
* @create 2023-03-22 17:24
* @desc
**/
@configuration
@propertysource("classpath:application.yml") //读取配置文件
@configurationproperties(prefix = "weixin") //读取weixin节点
@data //使用set方法将weixin节点中的值填充到当前类的属性中
public class wxpayconfig {
// 商户号
private string mchid;
// 商户api证书序列号
private string mchserialno;
// 商户私钥文件
private string privatekeypath;
// apiv3密钥
private string key;
// appid
private string appid;
// 微信服务器地址
private string domain;
// 接收结果通知地址
private string notifydomain;
/**
* 获取商户的私钥文件
*
* @param filename 证书地址
* @return 私钥文件
*/
public privatekey getprivatekey(string filename) {
try {
classpathresource classpathresource = new classpathresource(filename);
return pemutil.loadprivatekey(classpathresource.getinputstream());
} catch (ioexception e) {
throw new commonexception("私钥文件不存在");
}
}
/**
* 获取签名验证器
*/
@bean
public verifier getverifier() {
// 获取商户私钥
final privatekey privatekey = getprivatekey(privatekeypath);
// 私钥签名对象
privatekeysigner privatekeysigner = new privatekeysigner(mchserialno, privatekey);
// 身份认证对象
wechatpay2credentials wechatpay2credentials = new wechatpay2credentials(mchid, privatekeysigner);
// 获取证书管理器实例
certificatesmanager certificatesmanager = certificatesmanager.getinstance();
try {
// 向证书管理器增加需要自动更新平台证书的商户信息
certificatesmanager.putmerchant(mchid, wechatpay2credentials, key.getbytes(standardcharsets.utf_8));
} catch (ioexception | generalsecurityexception | httpcodeexception e) {
e.printstacktrace();
}
try {
return certificatesmanager.getverifier(mchid);
} catch (notfoundexception e) {
e.printstacktrace();
throw new commonexception("获取签名验证器失败");
}
}
/**
* 获取微信支付的远程请求对象
*
* @return http请求对象
*/
@bean
public closeablehttpclient getwxpayclient() {
// 获取签名验证器
verifier verifier = getverifier();
// 获取商户私钥
final privatekey privatekey = getprivatekey(privatekeypath);
wechatpayhttpclientbuilder builder = wechatpayhttpclientbuilder.create().withmerchant(mchid, mchserialno, privatekey)
.withvalidator(new wechatpay2validator(verifier));
return builder.build();
}
}
四、微信支付枚举类
import lombok.allargsconstructor;
import lombok.getter;
/**
* @author lihao
* @create 2023-03-22 17:21
* @desc 微信支付枚举类
**/
@allargsconstructor
@getter
public enum wxapitype {
/**
* native下单
*/
native_pay("/v3/pay/transactions/native"),
/**
* jsapi下单
*/
jsapi_pay("/v3/pay/transactions/jsapi"),
/**
* jsapi下单
*/
h5_pay("/v3/pay/transactions/h5"),
/**
* app下单
*/
app_pay("/v3/pay/transactions/app"),
/**
* 查询订单
*/
order_query_by_no("/v3/pay/transactions/out-trade-no/%s/?mchid=%s"),
/**
* 查询订单
*/
order_query_by_id("/v3/pay/transactions/id/%s?mchid=%s"),
/**
* 关闭订单
*/
close_order_by_no("/v3/pay/transactions/out-trade-no/%s/close"),
/**
* 申请退款
*/
domestic_refunds("/v3/refund/domestic/refunds"),
/**
* 查询单笔退款
*/
domestic_refunds_query("/v3/refund/domestic/refunds/%s"),
/**
* 申请交易账单
*/
trade_bills("/v3/bill/tradebill"),
/**
* 申请资金账单
*/
fund_flow_bills("/v3/bill/fundflowbill"),
/**
* 发起商家转账
*/
transfer_batches("/v3/transfer/batches");
/**
* 类型
*/
private final string type;
}
五、微信支付工具类(这边以native扫码支付为例)
(1)创建native扫码支付工具类 后面需要用到时传入参数直接调用即可
/**
* @author lihao
* @create 2023-03-23 9:58
* @desc native扫码支付工具类
**/
@slf4j
public class wxpaynativeutils {
public static map nativepay(wxpayconfig wxpayconfig, wechatpaynativeparam param, closeablehttpclient wxpayclient) throws exception {
gson gson = new gson();
// 创建post请求对象,里面输入的是地址,也就是那个https://api.wxpayxxxxx 那个,只不过我们直接去配置文件里面读取然后拼接出来了,懒得每次都输入一遍
httppost httppost = new httppost(wxpayconfig.getdomain().concat(wxapitype.native_pay.gettype()));
map paramsmap =new hashmap();
paramsmap.put("appid",wxpayconfig.getappid()); // 我们的appid
paramsmap.put("mchid",wxpayconfig.getmchid()); // 我们的商户id
paramsmap.put("description",param.getdescription()); // 扫码之后显示的标题
paramsmap.put("out_trade_no",param.getouttradeno()); // 商户订单号 我们自己生成的那个
// 这里就是微信响应给我们系统的那个地址 必须是能外网访问的
paramsmap.put("notify_url",wxpayconfig.getnotifydomain());
map amountmap = new hashmap();
amountmap.put("total",param.gettotal()); // 支付金额
amountmap.put("currency","cny"); // 交易货币的类型
paramsmap.put("amount",amountmap);
paramsmap.put("attach",param.getdeviceinfo());
// 将这个json对象转换成字符串,用于后面进行网络传输
string jsonparams = gson.tojson(paramsmap);
log.info("请求微信支付v3 native扫码支付接口参数 =========> " jsonparams);
// 设置请求体
stringentity entity = new stringentity(jsonparams,"utf-8");
entity.setcontenttype("application/json");
httppost.setentity(entity);
httppost.setheader("accept", "application/json");
//完成签名并执行请求
closeablehttpresponse response = wxpayclient.execute(httppost);
hashmap returnmap = new hashmap<>();
try {
string body = entityutils.tostring(response.getentity());
int statuscode = response.getstatusline().getstatuscode();
if (statuscode == 200) { //处理成功 有返回就会进入这里
log.info("请求微信支付v3 native扫码支付接口成功,返回结果 =========> " body);
} else if (statuscode == 204) { //处理成功,无返回就会进入到这里
system.out.println("success");
} else { // 接口调用失败的话就会进入这里
log.info("native下单失败,响应码 =====> " statuscode ",返回结果= " body);
hashmap resultmap = gson.fromjson(body, hashmap.class);
returnmap.put("err_code_des",resultmap.get("message"));
}
// 相微信那边返回的结果 我们将json返回转成一个map对象
hashmap resultmap = gson.fromjson(body, hashmap.class);
// 然后从这个map里面拿到code_url,这个是微信定义的,我们拿这个结果生成二维码
string code_url = resultmap.get("code_url");
returnmap.put("code_url",code_url);
return returnmap;
} finally {
response.close();
}
}
}
(2)native支付成功回调工具类
/**
* @author lihao
* @create 2023-03-23 11:40
* @desc
**/
@slf4j
public class wxpaycallbackutil {
/**
* 微信支付创建订单回调方法
* @param verifier 证书
* @param wxpayconfig 微信配置
* @param businesscallback 回调方法,用于处理业务逻辑
* @return json格式的string数据,直接返回给微信
*/
public static string wxpaysuccesscallback(httpservletrequest request, httpservletresponse response, verifier verifier, wxpayconfig wxpayconfig, consumer businesscallback) {
gson gson = new gson();
// 1.处理通知参数
final string body = httputils.readdata(request);
hashmap bodymap = gson.fromjson(body, hashmap.class);
// 2.签名验证
wechatpayvalidatorforrequest wechatforrequest = new wechatpayvalidatorforrequest(verifier, body, (string) bodymap.get("id"));
try {
if (!wechatforrequest.validate(request)) {
// 通知验签失败
response.setstatus(500);
final hashmap map = new hashmap<>();
map.put("code", "error");
map.put("message", "通知验签失败");
return gson.tojson(map);
}
} catch (ioexception e) {
e.printstacktrace();
}
// 3.获取明文数据
string plaintext = decryptfromresource(bodymap,wxpayconfig);
hashmap plaintextmap = gson.fromjson(plaintext, hashmap.class);
log.info("plaintextmap:{}",plaintextmap);
// 4.封装微信返回的数据
wxchatcallbacksuccessresult callbackdata = new wxchatcallbacksuccessresult();
callbackdata.setsuccesstime(string.valueof(plaintextmap.get("success_time")));
callbackdata.setorderid(string.valueof(plaintextmap.get("out_trade_no")));
callbackdata.settransactionid(string.valueof(plaintextmap.get("transaction_id")));
callbackdata.settradestate(string.valueof(plaintextmap.get("trade_state")));
callbackdata.settradetype(string.valueof(plaintextmap.get("trade_type")));
callbackdata.setattach(string.valueof(plaintextmap.get("attach")));
string amount = string.valueof(plaintextmap.get("amount"));
hashmap amountmap = gson.fromjson(amount, hashmap.class);
string total = string.valueof(amountmap.get("total"));
callbackdata.settotalmoney(new bigdecimal(total).movepointleft(2));
log.info("callbackdata:{}",callbackdata);
if ("success".equals(callbackdata.gettradestate())) {
// 执行业务逻辑
businesscallback.accept(callbackdata);
}
// 5.成功应答
response.setstatus(200);
final hashmap resultmap = new hashmap<>();
resultmap.put("code", "success");
resultmap.put("message", "成功");
return gson.tojson(resultmap);
}
/**
* 对称解密
*/
private static string decryptfromresource(hashmap bodymap, wxpayconfig wxpayconfig) {
// 通知数据
map resourcemap = (map) bodymap.get("resource");
// 数据密文
string ciphertext = resourcemap.get("ciphertext");
// 随机串
string nonce = resourcemap.get("nonce");
// 附加数据
string associatedata = resourcemap.get("associated_data");
aesutil aesutil = new aesutil(wxpayconfig.getkey().getbytes(standardcharsets.utf_8));
try {
return aesutil.decrypttostring(associatedata.getbytes(standardcharsets.utf_8), nonce.getbytes(standardcharsets.utf_8), ciphertext);
} catch (generalsecurityexception e) {
e.printstacktrace();
throw new commonexception("解密失败");
}
}
}
(3)请求参数
/**
* @author lihao
* @create 2023-03-23 10:02
* @desc 微信native支付参数
**/
@data
public class wechatpaynativeparam {
/**
* 扫码之后显示的标题
*/
private string description;
/**
* 商户订单号 我们自己生成的那个
*/
private string outtradeno;
/**
* 支付金额
*/
private bigdecimal total;
/**
* 自定义参数 具体看业务要求 无要求可不填
*/
private string deviceinfo;
}
(4)controller中调用native扫码支付工具类
@autowired
private wxpayconfig wxpayconfig;
@autowired
private closeablehttpclient wxpayclient;
@apioperation("微信支付v3版返回链接")
@saplatchecklogin
@postmapping("/nativepay")
public commonresult nativepay(@requestbody wechatpayparam payparam) throws exception {
wechatpaynativeparam param = new wechatpaynativeparam();
param.setdescription(payparam.getdescription());
//这里注意要保持商户订单号唯一
param.setouttradeno(payparam.getorderid() randomutil.randomnumbers(4));
param.setdeviceinfo(payparam.getorderid());
bigdecimal money = new bigdecimal(0.01);
param.settotal((money.multiply(new bigdecimal(100))).setscale(0,bigdecimal.round_half_down));
map map = wxpaynativeutils.nativepay(wxpayconfig,param,wxpayclient);
if(objectutil.isempty(map) || objectutil.isnotempty(map.get("err_code_des"))){
return commonresult.data(new wechatcoderesult(null,"fail",map.get("err_code_des").tostring()));
}
if(objectutil.isempty(map.get("code_url"))){
throw new commonexception("生成支付二维码失败!");
}
return commonresult.data(new wechatcoderesult(map.get("code_url").tostring(),"success",null));
}
@apioperation("微信支付回调接口")
@postmapping("/callback")
public string coursenative(httpservletrequest request, httpservletresponse response) {
return wxpaycallbackutil.wxpaysuccesscallback(request, response, verifier, wxpayconfig, callbackdata -> {
log.info("微信支付返回的信息:{}", callbackdata);
//这里处理自己的业务
wechatpayservice.payorder(callbackdata.getattach(),callbackdata.gettotalmoney().tostring(), callbackdata.gettransactionid());
});
}
六、附下其他几种j9九游会老哥俱乐部交流区的支付方式
(1)微信退款工具类
/**
* @author lihao
* @create 2023-03-23 11:18
* @desc 微信退款工具类
**/
@slf4j
public class wxpayrefundutil {
/**
* 发起微信退款申请
*
* @param wxpayconfig 微信配置信息
* @param param 微信支付申请退款请求参数
* @param wxpayclient 微信请求客户端
* @return
*/
public static string refundpay(wxpayconfig wxpayconfig, wechatrefundparam param, closeablehttpclient wxpayclient) {
// 1.获取请求参数的map格式
map paramsmap = getrefundparams(param);
// 2.获取请求对象
httppost httppost = gethttppost(wxpayconfig, wxapitype.domestic_refunds, paramsmap);
// 3.完成签名并执行请求
closeablehttpresponse response = null;
try {
response = wxpayclient.execute(httppost);
} catch (ioexception e) {
e.printstacktrace();
throw new commonexception("微信支付请求失败");
}
// 4.解析response对象
hashmap resultmap = resolverresponse(response);
log.info("============>发起微信退款参数:{}",resultmap);
if (resultmap != null) {
// 返回微信支付退款单号
return resultmap.get("out_refund_no");
}
return null;
}
/**
* 查询单笔退款
* @param wxpayconfig 微信配置信息
* @param outrefundno 商户退款单号
* @param wxpayclient 微信请求客户端
* @return
*/
public static map refundquery(wxpayconfig wxpayconfig, string outrefundno, closeablehttpclient wxpayclient) {
// 1.请求路径和对象
string url = string.format(wxpayconfig.getdomain().concat(wxapitype.domestic_refunds_query.gettype()),outrefundno);
httpget httpget = new httpget(url);
httpget.setheader("accept", "application/json");
// 2.完成签名并执行请求
closeablehttpresponse response = null;
try {
response = wxpayclient.execute(httpget);
} catch (ioexception e) {
e.printstacktrace();
throw new commonexception("微信支付请求失败");
}
// 3.解析返回的数据
map map = resolverresponse(response);
log.info("微信支付查询单笔退款信息========>{}",map);
return map;
}
/**
* 解析响应数据
*
* @param response 发送请求成功后,返回的数据
* @return 微信返回的参数
*/
private static hashmap resolverresponse(closeablehttpresponse response) {
try {
// 1.获取请求码
int statuscode = response.getstatusline().getstatuscode();
// 2.获取返回值 string 格式
final string bodyasstring = entityutils.tostring(response.getentity());
gson gson = new gson();
if (statuscode == 200) {
// 3.如果请求成功则解析成map对象返回
hashmap resultmap = gson.fromjson(bodyasstring, hashmap.class);
return resultmap;
} else {
if (stringutils.isnoneblank(bodyasstring)) {
log.error("微信支付请求失败,提示信息:{}", bodyasstring);
// 4.请求码显示失败,则尝试获取提示信息
hashmap resultmap = gson.fromjson(bodyasstring, hashmap.class);
throw new commonexception(resultmap.get("message"));
}
log.error("微信支付请求失败,未查询到原因,提示信息:{}", response);
// 其他异常,微信也没有返回数据,这就需要具体排查了
throw new ioexception("request failed");
}
} catch (exception e) {
e.printstacktrace();
throw new commonexception(e.getmessage());
} finally {
try {
response.close();
} catch (ioexception e) {
e.printstacktrace();
}
}
}
/**
* 获取请求对象(post请求)
*
* @param wxpayconfig 微信配置类
* @param apitype 接口请求地址
* @param paramsmap 请求参数
* @return post请求对象
*/
private static httppost gethttppost(wxpayconfig wxpayconfig, wxapitype apitype, map paramsmap) {
// 1.设置请求地址
httppost httppost = new httppost(wxpayconfig.getdomain().concat(apitype.gettype()));
// 2.设置请求数据
gson gson = new gson();
string jsonparams = gson.tojson(paramsmap);
// 3.设置请求信息
stringentity entity = new stringentity(jsonparams, "utf-8");
entity.setcontenttype("application/json");
httppost.setentity(entity);
httppost.setheader("accept", "application/json");
return httppost;
}
/**
* 封装微信支付申请退款请求参数
*
* @param param 微信支付申请退款请求参数
* @return 封装后的map微信支付申请退款请求参数对象
*/
private static map getrefundparams(wechatrefundparam param) {
map paramsmap = new hashmap<>();
if (stringutils.isnoneblank(param.gettransactionid())) {
paramsmap.put("transaction_id", param.gettransactionid());
} else if (stringutils.isnoneblank(param.getorderid())) {
paramsmap.put("out_trade_no", param.getorderid());
} else {
throw new commonexception("微信支付订单号和商户订单号必须填写一个");
}
paramsmap.put("out_refund_no", param.getrefundorderid());
if (stringutils.isnoneblank(param.getreason())) {
paramsmap.put("reason", param.getreason());
}
//paramsmap.put("notify_url", wxpayconfig.getnotifydomain().concat(param.getnotify().gettype()));
map amountmap = new hashmap<>();
amountmap.put("refund", param.getrefundmoney().multiply(new bigdecimal(100)).setscale(0,bigdecimal.round_half_down));
amountmap.put("total", param.gettotalmoney().multiply(new bigdecimal(100)).setscale(0,bigdecimal.round_half_down));
amountmap.put("currency", "cny");
paramsmap.put("amount", amountmap);
return paramsmap;
}
}
(2)订单查询工具类
/**
* @author lihao
* @create 2023-03-23 15:49
* @desc 微信支付查询订单信息工具类
**/
@slf4j
public class wxpaysearchorderutil {
/**
* 根据微信支付系统生成的订单号查询订单详情
* @param wxpayconfig 微信支付配置信息
* @param transactionid 微信支付系统生成的订单号
* @param wxpayclient 微信支付客户端请求对象
* @return 微信订单对象
*/
public static wxchatcallbacksuccessresult searchbytransactionid(wxpayconfig wxpayconfig, string transactionid, closeablehttpclient wxpayclient) {
// 1.请求路径和对象
string url = string.format(wxpayconfig.getdomain().concat(wxapitype.order_query_by_id.gettype()),transactionid,wxpayconfig.getmchid());;
httpget httpget = new httpget(url);
httpget.setheader("accept", "application/json");
// 2.完成签名并执行请求
closeablehttpresponse response = null;
try {
response = wxpayclient.execute(httpget);
} catch (ioexception e) {
e.printstacktrace();
throw new commonexception("微信支付请求失败");
}
// 3.解析返回的数据
wxchatcallbacksuccessresult callbackdata = resolverresponse(response);
log.info("微信支付根据订单号查询信息========>callbackdata:{}",callbackdata);
return callbackdata;
}
/**
* 根据微信支付系统生成的订单号查询订单详情
* @param wxpayconfig 微信支付配置信息
* @param orderid 我们自己的订单id
* @param wxpayclient 微信支付客户端请求对象
* @return 微信订单对象
*/
public static wxchatcallbacksuccessresult searchbyorderid(wxpayconfig wxpayconfig, string orderid, closeablehttpclient wxpayclient) {
// 1.请求路径和对象
string url = string.format(wxpayconfig.getdomain().concat(wxapitype.order_query_by_no.gettype()),orderid,wxpayconfig.getmchid());
httpget httpget = new httpget(url);
httpget.setheader("accept", "application/json");
// 2.完成签名并执行请求
closeablehttpresponse response = null;
try {
response = wxpayclient.execute(httpget);
} catch (ioexception e) {
e.printstacktrace();
throw new commonexception("微信支付请求失败");
}
// 3.解析返回的数据
wxchatcallbacksuccessresult callbackdata = resolverresponse(response);
log.info("微信支付根据商户订单号查询信息========>callbackdata:{}",callbackdata);
return callbackdata;
}
/**
* 解析响应数据
* @param response 发送请求成功后,返回的数据
* @return 微信返回的参数
*/
private static wxchatcallbacksuccessresult resolverresponse(closeablehttpresponse response) {
try {
// 1.获取请求码
int statuscode = response.getstatusline().getstatuscode();
// 2.获取返回值 string 格式
final string bodyasstring = entityutils.tostring(response.getentity());
gson gson = new gson();
if (statuscode == 200) {
// 3.如果请求成功则解析成map对象返回
hashmap resultmap = gson.fromjson(bodyasstring, hashmap.class);
// 4.封装成我们需要的数据
wxchatcallbacksuccessresult callbackdata = new wxchatcallbacksuccessresult();
callbackdata.setsuccesstime(string.valueof(resultmap.get("success_time")));
callbackdata.setorderid(string.valueof(resultmap.get("out_trade_no")));
callbackdata.settransactionid(string.valueof(resultmap.get("transaction_id")));
callbackdata.settradestate(string.valueof(resultmap.get("trade_state")));
callbackdata.settradetype(string.valueof(resultmap.get("trade_type")));
callbackdata.setattach(string.valueof(resultmap.get("attach")));
string amount = string.valueof(resultmap.get("amount"));
hashmap amountmap = gson.fromjson(amount, hashmap.class);
string total = string.valueof(amountmap.get("total"));
callbackdata.settotalmoney(new bigdecimal(total).movepointleft(2));
return callbackdata;
} else {
if (stringutils.isnoneblank(bodyasstring)) {
log.error("微信支付请求失败,提示信息:{}", bodyasstring);
// 4.请求码显示失败,则尝试获取提示信息
hashmap resultmap = gson.fromjson(bodyasstring, hashmap.class);
throw new commonexception(resultmap.get("message"));
}
log.error("微信支付请求失败,未查询到原因,提示信息:{}", response);
// 其他异常,微信也没有返回数据,这就需要具体排查了
throw new ioexception("request failed");
}
} catch (exception e) {
e.printstacktrace();
throw new commonexception(e.getmessage());
} finally {
try {
response.close();
} catch (ioexception e) {
e.printstacktrace();
}
}
}
}
(3)商家发起转账工具类
/**
* @author lihao
* @create 2023-03-22 17:21
* @desc 发起商家转账工具类
**/
@slf4j
public class wxpaytransferbatchesutils {
/**
* 发起商家转账,支持批量转账
*
* @param wxpayconfig 微信配置信息
* @param param 转账请求参数
* @param wxpayclient 微信请求客户端()
* @return 微信支付二维码地址
*/
public static string transferbatches(wxpayconfig wxpayconfig, wechattransferbatchesparam param, closeablehttpclient wxpayclient) {
// 1.获取请求参数的map格式
map paramsmap = getparams(wxpayconfig, param);
// 2.获取请求对象,wxapitype.transfer_batches="/v3/transfer/batches"
httppost httppost = gethttppost(wxpayconfig, wxapitype.transfer_batches , paramsmap);
// 3.完成签名并执行请求
closeablehttpresponse response = null;
try {
response = wxpayclient.execute(httppost);
} catch (ioexception e) {
e.printstacktrace();
throw new commonexception("商家转账请求失败");
}
// 4.解析response对象
hashmap resultmap = resolverresponse(response);
if (resultmap != null) {
// batch_id微信批次单号,微信商家转账系统返回的唯一标识
return resultmap.get("batch_id");
}
return null;
}
/**
* 解析响应数据
* @param response 发送请求成功后,返回的数据
* @return 微信返回的参数
*/
private static hashmap resolverresponse(closeablehttpresponse response) {
try {
// 1.获取请求码
int statuscode = response.getstatusline().getstatuscode();
// 2.获取返回值 string 格式
final string bodyasstring = entityutils.tostring(response.getentity());
gson gson = new gson();
if (statuscode == 200) {
// 3.如果请求成功则解析成map对象返回
hashmap resultmap = gson.fromjson(bodyasstring, hashmap.class);
return resultmap;
} else {
if (stringutils.isnoneblank(bodyasstring)) {
log.error("商户转账请求失败,提示信息:{}", bodyasstring);
// 4.请求码显示失败,则尝试获取提示信息
hashmap resultmap = gson.fromjson(bodyasstring, hashmap.class);
throw new commonexception(resultmap.get("message"));
}
log.error("商户转账请求失败,未查询到原因,提示信息:{}", response);
// 其他异常,微信也没有返回数据,这就需要具体排查了
throw new ioexception("request failed");
}
} catch (exception e) {
e.printstacktrace();
throw new commonexception(e.getmessage());
} finally {
try {
response.close();
} catch (ioexception e) {
e.printstacktrace();
}
}
}
/**
* 获取请求对象(post请求)
*
* @param wxpayconfig 微信配置类
* @param apitype 接口请求地址
* @param paramsmap 请求参数
* @return post请求对象
*/
private static httppost gethttppost(wxpayconfig wxpayconfig, wxapitype apitype, map paramsmap) {
// 1.设置请求地址
httppost httppost = new httppost(wxpayconfig.getdomain().concat(apitype.gettype()));
// 2.设置请求数据
gson gson = new gson();
string jsonparams = gson.tojson(paramsmap);
// 3.设置请求信息
stringentity entity = new stringentity(jsonparams, "utf-8");
entity.setcontenttype("application/json");
httppost.setentity(entity);
httppost.setheader("accept", "application/json");
return httppost;
}
/**
* 封装转账请求参数
*
* @param wxpayconfig 微信的配置文件
* @param param 批量转账请求数据
* @return 封装后的map对象
*/
private static map getparams(wxpayconfig wxpayconfig, wechattransferbatchesparam param) {
map paramsmap = new hashmap<>();
paramsmap.put("appid", wxpayconfig.getappid());
paramsmap.put("out_batch_no", param.getbatchid());
paramsmap.put("batch_name", param.gettitle());
paramsmap.put("batch_remark", param.getremark());
paramsmap.put("total_amount", param.gettotalmoney().multiply(new bigdecimal("100")).intvalue());
paramsmap.put("total_num", param.gettransferdetaillist().size());
// 存储转账明细,一次最多三千笔
if (param.gettransferdetaillist().size() > 3000) {
throw new commonexception("发起批量转账一次最多三千笔");
}
list
本人针对j9九游会老哥俱乐部交流区的支付方式做了一个简单的通用类(包含native方式、jsapi方式、app方式),如果用不到可不采用
支付通用参数
/**
* @author lihao
* @create 2023-03-22 17:48
* @desc 微信支付通用参数
**/
@data
public class wechatbasepaydata {
/**
* 商品描述
*/
private string title;
/**
* 商家订单号,对应 out_trade_no
*/
private string orderid;
/**
* 订单金额
*/
private bigdecimal price;
/**
* 回调地址
*/
private string notify;
}
微信支付通用配置
/**
* @author lihao
* @create 2023-03-22 17:45
* @desc 微信通用配置
**/
@slf4j
public class wxpaycommon {
/**
* 创建微信支付订单-native方式
*
* @param wxpayconfig 微信配置信息
* @param basepaydata 基础请求信息,商品标题、商家订单id、订单价格
* @param wxpayclient 微信请求客户端
* @return 微信支付二维码地址
*/
public static string wxnativepay(wxpayconfig wxpayconfig, wechatbasepaydata basepaydata, closeablehttpclient wxpayclient) {
// 1.获取请求参数的map格式
map paramsmap = getbasepayparams(wxpayconfig, basepaydata);
// 2.获取请求对象
httppost httppost = gethttppost(wxpayconfig, wxapitype.native_pay, paramsmap);
// 3.完成签名并执行请求
closeablehttpresponse response = null;
try {
response = wxpayclient.execute(httppost);
} catch (ioexception e) {
e.printstacktrace();
throw new commonexception("微信支付请求失败");
}
// 4.解析response对象
hashmap resultmap = resolverresponse(response);
if (resultmap != null) {
// native请求返回的是二维码链接,前端将链接转换成二维码即可
return resultmap.get("code_url");
}
return null;
}
/**
* 创建微信支付订单-jsapi方式
*
* @param wxpayconfig 微信配置信息
* @param basepaydata 基础请求信息,商品标题、商家订单id、订单价格
* @param openid 通过微信小程序或者公众号获取到用户的openid
* @param wxpayclient 微信请求客户端
* @return 微信支付二维码地址
*/
public static string wxjsapipay(wxpayconfig wxpayconfig, wechatbasepaydata basepaydata, string openid,closeablehttpclient wxpayclient) {
// 1.获取请求参数的map格式
map paramsmap = getbasepayparams(wxpayconfig, basepaydata);
// 1.1 添加支付者信息
map payermap = new hashmap();
payermap.put("openid",openid);
paramsmap.put("payer",payermap);
// 2.获取请求对象
httppost httppost = gethttppost(wxpayconfig, wxapitype.jsapi_pay, paramsmap);
// 3.完成签名并执行请求
closeablehttpresponse response = null;
try {
response = wxpayclient.execute(httppost);
} catch (ioexception e) {
e.printstacktrace();
throw new commonexception("微信支付请求失败");
}
// 4.解析response对象
hashmap resultmap = resolverresponse(response);
if (resultmap != null) {
// native请求返回的是二维码链接,前端将链接转换成二维码即可
return resultmap.get("prepay_id");
}
return null;
}
/**
* 创建微信支付订单-app方式
*
* @param wxpayconfig 微信配置信息
* @param basepaydata 基础请求信息,商品标题、商家订单id、订单价格
* @param wxpayclient 微信请求客户端
* @return 微信支付二维码地址
*/
public static string wxapppay(wxpayconfig wxpayconfig, wechatbasepaydata basepaydata, closeablehttpclient wxpayclient) {
// 1.获取请求参数的map格式
map paramsmap = getbasepayparams(wxpayconfig, basepaydata);
// 2.获取请求对象
httppost httppost = gethttppost(wxpayconfig, wxapitype.app_pay, paramsmap);
// 3.完成签名并执行请求
closeablehttpresponse response = null;
try {
response = wxpayclient.execute(httppost);
} catch (ioexception e) {
e.printstacktrace();
throw new commonexception("微信支付请求失败");
}
// 4.解析response对象
hashmap resultmap = resolverresponse(response);
if (resultmap != null) {
// native请求返回的是二维码链接,前端将链接转换成二维码即可
return resultmap.get("prepay_id");
}
return null;
}
/**
* 解析响应数据
* @param response 发送请求成功后,返回的数据
* @return 微信返回的参数
*/
private static hashmap resolverresponse(closeablehttpresponse response) {
try {
// 1.获取请求码
int statuscode = response.getstatusline().getstatuscode();
// 2.获取返回值 string 格式
final string bodyasstring = entityutils.tostring(response.getentity());
gson gson = new gson();
if (statuscode == 200) {
// 3.如果请求成功则解析成map对象返回
hashmap resultmap = gson.fromjson(bodyasstring, hashmap.class);
return resultmap;
} else {
if (stringutils.isnoneblank(bodyasstring)) {
log.error("微信支付请求失败,提示信息:{}", bodyasstring);
// 4.请求码显示失败,则尝试获取提示信息
hashmap resultmap = gson.fromjson(bodyasstring, hashmap.class);
throw new commonexception(resultmap.get("message"));
}
log.error("微信支付请求失败,未查询到原因,提示信息:{}", response);
// 其他异常,微信也没有返回数据,这就需要具体排查了
throw new ioexception("request failed");
}
} catch (exception e) {
e.printstacktrace();
throw new commonexception(e.getmessage());
} finally {
try {
response.close();
} catch (ioexception e) {
e.printstacktrace();
}
}
}
/**
* 获取请求对象(post请求)
*
* @param wxpayconfig 微信配置类
* @param apitype 接口请求地址
* @param paramsmap 请求参数
* @return post请求对象
*/
private static httppost gethttppost(wxpayconfig wxpayconfig, wxapitype apitype, map paramsmap) {
// 1.设置请求地址
httppost httppost = new httppost(wxpayconfig.getdomain().concat(apitype.gettype()));
// 2.设置请求数据
gson gson = new gson();
string jsonparams = gson.tojson(paramsmap);
// 3.设置请求信息
stringentity entity = new stringentity(jsonparams, "utf-8");
entity.setcontenttype("application/json");
httppost.setentity(entity);
httppost.setheader("accept", "application/json");
return httppost;
}
/**
* 封装基础通用请求参数
*
* @param wxpayconfig 微信的配置文件
* @param basepaydata 微信支付基础请求数据
* @return 封装后的map对象
*/
private static map getbasepayparams(wxpayconfig wxpayconfig, wechatbasepaydata basepaydata) {
map paramsmap = new hashmap<>();
paramsmap.put("appid", wxpayconfig.getappid());
paramsmap.put("mchid", wxpayconfig.getmchid());
// 如果商品名称过长则截取
string title = basepaydata.gettitle().length() > 62 ? basepaydata.gettitle().substring(0, 62) : basepaydata.gettitle();
paramsmap.put("description", title);
paramsmap.put("out_trade_no", basepaydata.getorderid());
paramsmap.put("notify_url", wxpayconfig.getnotifydomain());
map amountmap = new hashmap<>();
amountmap.put("total", basepaydata.getprice().multiply(new bigdecimal("100")).intvalue());
paramsmap.put("amount", amountmap);
return paramsmap;
}
}
支付返回值实体类
package com.qz.client.modular.pay.result;
import io.swagger.annotations.apimodelproperty;
import lombok.getter;
import lombok.setter;
/**
* @author:lihao
* @create: 2023-01-09 13:12
* @description:
*/
@setter
@getter
public class wechatcoderesult {
@apimodelproperty(value = "微信支付二维码链接")
private string code_url;
@apimodelproperty(value = "错误:fail 成功:success")
private string result_code;
@apimodelproperty(value = "错误详情")
private string err_code_des;
public wechatcoderesult() {
}
public wechatcoderesult(string code_url, string result_code, string err_code_des) {
this.code_url = code_url;
this.result_code = result_code;
this.err_code_des = err_code_des;
}
}
本文标签: springboot
j9九游会老哥俱乐部交流区的版权声明:本文标题:springboot集成微信支付v3 sdk 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1727371463a1111220.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论