微信扫码支付
以下主要是针对微信支付V3接口进行的整合,且为Native支付
前期准备工作
1️⃣:获取微信相关数据
#绑定支付的appid
#商户id
#商户支付秘钥wechatKey,这个需要V3的
#证书序列号
#私钥文件(.pem文件)
#下面给出了相应的链接
⚠️:这里千万别用微信服务商去注册,原因见下图
上面的参数都获取到后,就可以进行springboot的整合了
2️⃣:导入maven坐标
<!--微信支付-->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.6</version>
</dependency>
package com.test.test.api.wechat.pay;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.partnerpayments.nativepay.model.Transaction;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* @author xiaobo
* @date 2023/3/8
*/
@Controller
@Slf4j
@RequestMapping("/wechat")
public class WechatPayApi extends BaseController {
private static final String APP_ID = "";
private static final String MERCHANT_ID = "";
private static final String WECHAT_KEY = "";
private static final String MERCHANT_SERIAL_NUMBER = "";
private static final String NOTIFY_URL = "";
public static NativePayService service;
public static Config config = null;
public static final String WECHAT_PAY_SIGNATURE = "Wechatpay-Signature";
public static final String WECHAT_PAY_TIMESTAMP = "Wechatpay-Timestamp";
public static final String WECHAT_PAY_SIGNATURE_TYPE = "Wechatpay-Signature-Type";
public static final String WECHAT_PAY_SERIAL = "Wechatpay-Serial";
public static final String WECHAT_PAY_NONCE = "Wechatpay-Nonce";
/**
* Native支付预下单
*/
@RequestMapping("prepay")
@ResponseBody
public RespResult wechatPay(double total_amount) {
PrepayRequest prepayRequest = new PrepayRequest();
Amount amount = new Amount();
// total为分
amount.setTotal((int) (total_amount * 100));
prepayRequest.setAmount(amount);
prepayRequest.setMchid(MERCHANT_ID);
prepayRequest.setAppid(APP_ID);
prepayRequest.setNotifyUrl(NOTIFY_URL);
prepayRequest.setDescription("账户充值");
// 这里的订单号要保证唯一,这种方法不推荐(因为并发高的情况下会出现订单号不唯一)
prepayRequest.setOutTradeNo(new SimpleDateFormat("yyyyMMddhhmmss").format(new Date()) + RandomUtil.randomNumbers(4));
PrepayResponse prepayResponse = service.prepay(prepayRequest);
// TODO 数据库处理订单(这里应该相应的生成订单)
// 返回成功,以及相应的二维码地址(前端需要进行转换为二维码)
return RespResult.success(prepayResponse.getCodeUrl(), jsonObject);
}
return RespResult.fail("获取微信支付码失败!");
}
@ResponseBody
@PostMapping("success")
public RespResult success(HttpServletRequest request) throws IOException {
// 读取请求头内容
String serialNumber = request.getHeader(WECHAT_PAY_SERIAL);
String nonce = request.getHeader(WECHAT_PAY_NONCE);
String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
String signType = request.getHeader(WECHAT_PAY_SIGNATURE_TYPE);
log.error(serialNumber, nonce, signature, timestamp);
// 获取请求体内容
ServletInputStream servletInputStream = request.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(servletInputStream));
StringBuffer stringBuffer = new StringBuffer();
String s;
while ((s = bufferedReader.readLine()) != null) {
stringBuffer.append(s);
}
// 构造 RequestParam
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(serialNumber)
.nonce(nonce)
.signature(signature)
.timestamp(timestamp)
// 若未设置signType,默认值为 WECHATPAY2-SHA256-RSA2048
.signType(signType)
.body(stringBuffer.toString())
.build();
// 初始化 NotificationParser
NotificationParser parser = new NotificationParser((NotificationConfig) config);
// 验签并解密报文
Transaction decryptObject = parser.parse(requestParam, Transaction.class);
log.error(decryptObject.toString());
Map params = new HashMap(3);
Map resultMap = (Map) JSON.parse(stringBuffer.toString());
// TODO 你的业务逻辑处理
return RespResult.success("成功!");
}
return RespResult.success("失败!");
}
@PostConstruct
public static NativePayService initializeWechatConfiguration() throws FileNotFoundException {
// 初始化商户配置
String privateKeyPath = Objects.requireNonNull(KuocaiCdnBootApplication.class.getResource("/apiclient_key.pem")).getPath();
if (config == null) {
config =
new RSAAutoCertificateConfig.Builder()
.merchantId(MERCHANT_ID)
// 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(MERCHANT_SERIAL_NUMBER)
.apiV3Key(WECHAT_KEY)
.build();
}
if (service == null) {
service = new NativePayService.Builder().config(config).build();
}
log.info("初始化微信配置成功~~~~~~");
// 初始化服务
return service;
}
}
注意:这里的回调接口一定是域名下的接口,且可以访问,后面没参数
相应的微信V3接口文档说明如下