1,接入前准备:
- 接入模式选择直连模式;
- 申请小程序,得到APPID,并开通微信支付;
- 申请微信商户号,得到mchid,并绑定APPID;
- 配置商户API key,下载并配置商户证书,根据微信官方文档操作:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_1.shtml
- 上面都配置完之后会得到:小程序APPID、商户号mchid、商户证书序列号、API_V3密钥、商户私钥。
2,代码开发
引入微信支付API v3依赖
<!--微信支付依赖 v3版本-->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.2.2</version>
</dependency>
微信参数常量类:WechatPayConstant 参数自行更换
package com.office.miniapp.constants;
/**
* @InterfaceName: WechatPayConstant
* @Description: 微信支付常量类
* @Authror: XQD
* @Date: 2022/1/6 15:02
*/
public interface WechatPayConstant {
/**
* 支付结果回调地址
*/
String NOTIFY_URL = "线上域名地址/miniapp/wxPay/callback";
/**
* 退款结果回调地址
*/
String REFUNDS_URL = "线上域名地址/miniapp/refunds/callback";
/**
* 商户号
*/
String MCH_ID = "***";
/**
* 商户证书序列号
*/
String MCH_SERIAL_NO = "***";
/**
* API_V3密钥
*/
String API_V3KEY = "***";
/**
* 小程序appId
*/
String MP_APP_ID = "***";
/**
* 商户私钥
*/
String PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" +
"省略..." +
"-----END PRIVATE KEY-----\n";
/**
* jsapi下单url
*/
String V3_JSAPI_URL = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
/**
* 商户订单号查询url
*/
String V3_OUT_TRADE_NO = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}";
/**
* 关闭订单url
*/
String V3_CLOSE = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}/close";
}
微信支付工具类:WxPayUtil (自己封装的)
package com.office.miniapp.utils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.office.miniapp.constants.WechatPayConstant;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
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.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.Base64;
/**
* @ClassName: WxPayUtil
* @Description: 微信支付工具类
* @Authror: XQD
* @Date: 2022/8/13 23:04
*/
@Component
public class WxPayUtil {
/**
* @Description: 获取httpClient
* @Param: []
* @return: org.apache.http.impl.client.CloseableHttpClient
* @Author: XQD
* @Date:2022/8/13 23:16
*/
public static CloseableHttpClient getHttpClient() {
CloseableHttpClient httpClient = null;
// 加载商户私钥(privateKey:私钥字符串)
try {
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
new ByteArrayInputStream(WechatPayConstant.PRIVATE_KEY.getBytes("utf-8")));
//使用自动更新的签名验证器,不需要传入证书
AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
new WechatPay2Credentials(WechatPayConstant.MCH_ID, new PrivateKeySigner(WechatPayConstant.MCH_SERIAL_NO, merchantPrivateKey)),
WechatPayConstant.API_V3KEY.getBytes("utf-8"));
// 初始化httpClient
httpClient = WechatPayHttpClientBuilder.create()
.withMerchant(WechatPayConstant.MCH_ID, WechatPayConstant.MCH_SERIAL_NO, merchantPrivateKey)
.withValidator(new WechatPay2Validator(verifier))
.build();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return httpClient;
}
/**
* @Description: 生成签名
* @Param: [message]
* @return: java.lang.String
* @Author: XQD
* @Date:2022/6/7 16:00
*/
public static String sign(byte[] message) throws Exception {
Signature sign = Signature.getInstance("SHA256withRSA");
PrivateKey privateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(WechatPayConstant.PRIVATE_KEY.getBytes("utf-8")));
sign.initSign(privateKey);
sign.update(message);
return Base64.getEncoder().encodeToString(sign.sign());
}
/**
* @Description: 验证签名
* @Param: [serial, message, signature]请求头中带的序列号, 验签名串, 请求头中的应答签名
* @return: boolean
* @Author: XQD
* @Date:2021/9/14 10:36
*/
public static boolean signVerify(String serial, String message, String signature) {
AutoUpdateCertificatesVerifier verifier = null;
try {
// 加载商户私钥(privateKey:私钥字符串)
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
new ByteArrayInputStream(WechatPayConstant.PRIVATE_KEY.getBytes("utf-8")));
//使用自动更新的签名验证器,不需要传入证书
verifier = new AutoUpdateCertificatesVerifier(
new WechatPay2Credentials(WechatPayConstant.MCH_ID, new PrivateKeySigner(WechatPayConstant.MCH_SERIAL_NO, merchantPrivateKey)),
WechatPayConstant.API_V3KEY.getBytes("utf-8"));
return verifier.verify(serial, message.getBytes("utf-8"), signature);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return false;
}
/**
* @Description: 解密订单信息
* @Param: [body] 应答报文主体
* @return: java.lang.String
* @Author: XQD
* @Date:2021/9/14 11:48
*/
public static String decryptOrder(String body) {
try {
AesUtil aesUtil = new AesUtil(WechatPayConstant.API_V3KEY.getBytes("utf-8"));
ObjectMapper objectMapper = new ObjectMapper();
JsonNode node = objectMapper.readTree(body);
JsonNode resource = node.get("resource");
String ciphertext = resource.get("ciphertext").textValue();
String associatedData = resource.get("associated_data").textValue();
String nonce = resource.get("nonce").textValue();
return aesUtil.decryptToString(associatedData.getBytes("utf-8"), nonce.getBytes("utf-8"), ciphertext);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
return "";
}
}
下单接口调用
下单功能实现,返回预支付交易会话标识prepay_id
/**
* @Description: 小程序下单
* @Param: [userId, orders]
* @return: java.lang.Object
* @Author: XQD
* @Date:2022/8/13 18:48
*/
@Override
public CommonResult submitOrder() throws Exception {
// 小程序下单
CloseableHttpClient httpClient = WxPayUtil.getHttpClient();
HttpPost httpPost = new HttpPost(WechatPayConstant.V3_JSAPI_URL);
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode rootNode = objectMapper.createObjectNode();
rootNode.put("mchid", WechatPayConstant.MCH_ID)
.put("appid", WechatPayConstant.MP_APP_ID)
.put("notify_url", WechatPayConstant.NOTIFY_URL)
.put("description", "商品描述信息")
.put("out_trade_no", System.currentTimeMillis() + "");
rootNode.putObject("amount")
.put("total", 100);// 订单支付金额
rootNode.putObject("payer")
.put("openid", "小程序用户openid");
objectMapper.writeValue(bos, rootNode);
httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
//完成签名并执行请求
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
//处理成功返回的数据
String body= EntityUtils.toString(response.getEntity());
//JSONObject jsonObject = JSON.parseObject(body);
//获取预支付交易会话标识 prepay_id
//String prepayId= jsonObject.getString("prepay_id");
//把上面的订单信息存入订单数据库
return body;
} else if (statusCode == 204) {
// 处理成功,无返回Body
return "success";
} else {
System.out.println("failed,resp code = " + statusCode + ",return body = " + EntityUtils.toString(response.getEntity()));
throw new IOException("request failed");
}
} finally {
response.close();
}
}
到这里代表下单操作完成了。把预支付交易id(prepay_id)返回前端,进行拉起支付操作文章来源:https://www.toymoban.com/news/detail-495906.html
查询订单接口调用
/**
* @Description: 查询订单
* @Param: [outTradeNo] 商户订单号
* @return: java.lang.Object
* @Author: XQD
* @Date:2022/8/14 21:43
*/
@Override
public Object queryOrder(String outTradeNo) throws Exception {
CloseableHttpClient httpClient = WxPayUtil.getHttpClient();
String v3_out_trade_no = WechatPayConstant.V3_OUT_TRADE_NO.replaceFirst("\\{out_trade_no}", outTradeNo);
HttpGet httpGet = new HttpGet(v3_out_trade_no + "?mchid=" + WechatPayConstant.MCH_ID);
httpGet.addHeader("Accept", "application/json");
CloseableHttpResponse response = httpClient.execute(httpGet);
String bodyAsString = EntityUtils.toString(response.getEntity());
System.out.println(bodyAsString);
return bodyAsString;
}
关闭订单接口调用
/**
* @Description: 关闭订单
* @Param: [outTradeNo] 商户订单号
* @return: java.lang.Object
* @Author: XQD
* @Date:2022/8/14 21:43
*/
@Override
public Object closeOrder(String outTradeNo) throws Exception {
CloseableHttpClient httpClient = WxPayUtil.getHttpClient();
String v3_close = WechatPayConstant.V3_CLOSE.replaceFirst("\\{out_trade_no}", outTradeNo);
HttpPost httpPost = new HttpPost(v3_close);
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode rootNode = objectMapper.createObjectNode();
rootNode.put("mchid", WechatPayConstant.MCH_ID);
objectMapper.writeValue(bos, rootNode);
httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
CloseableHttpResponse response = httpClient.execute(httpPost);
// 状态码 204表示关单成功
int statusCode = response.getStatusLine().getStatusCode();
log.info("关闭订单返回码:{}", statusCode);
if (statusCode == 204) {
return "关单成功";
}
return "关单失败";
}
下一篇: SpringBoot对接微信小程序支付功能开发(二,支付回调功能)文章来源地址https://www.toymoban.com/news/detail-495906.html
到了这里,关于SpringBoot对接微信小程序支付功能开发(一,下单功能)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!