1.项目中加入相关maven配置
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.12</version>
</dependency>
2.yml中增加微信相关配置信息
security:
captcha:
#商户appId
appId: xxx
#商户号
merchantId: xxx
#微信证书
privateKeyPath: D:\\apiclient_key.pem
#商户证书序列号
merchantSerialNumber: xxx
#商户APIV3密钥
apiV3Key: xxxx
#回调接口
notifyUrl: https://xxx/weiXinPay/callback/
- java中相关配置代码
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
@RefreshScope
@Configuration
//读取wxpay节点
@ConfigurationProperties(prefix = "security.captcha")
@Data //使用set方法将wxpay节点中的值填充到当前类的属性中
public class WxPayConfig {
public String merchantId;
public String appId;
/** 商户API私钥路径 */
public String privateKeyPath;
/** 商户证书序列号 */
public String merchantSerialNumber;
/** 商户APIV3密钥 */
public String apiV3Key;
public String notifyUrl;
}
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class WxInitUtils {
//商户的全局配置类
public static Config instance;
/**
* 定义商户的全局配置信息,要求一个商户号对应一个配置
* 不能重复生成配置
* RSAAutoCertificateConfig 会利用 AutoCertificateService 自动下载微信支付平台证书。
* AutoCertificateService 将启动一个后台线程,定期(目前为每60分钟)更新证书,
* 以实现证书过期时的平滑切换。
* 在每次构建 RSAAutoCertificateConfig 时,
* SDK 首先会使用传入的商户参数下载一次微信支付平台证书。 如果下载成功,SDK 会将商户参数注册或更
* 新至 AutoCertificateService。若下载失败,将会抛出异常。
* 为了提高性能,建议将配置类作为全局变量。 复用 RSAAutoCertificateConfig
* 可以减少不必要的证书下载,避免资源浪费。 只有在配置发生变更时,
* 才需要重新构造 RSAAutoCertificateConfig。
*/
public static Config getInstance(WxPayConfig wxPayConfig){
if (instance == null){
//如果实例不存在,创建一个新的实例
synchronized (WxPayConfig.class){
//双重检查锁定,防止多线程竞争时创建多个实例
if (instance == null){
try{
if(wxPayConfig == null){
log.info("配置信息加载出错===");
return null;
}
instance = new RSAAutoCertificateConfig.Builder()
.merchantId(wxPayConfig.getMerchantId())
.privateKeyFromPath(wxPayConfig.getPrivateKeyPath())
.merchantSerialNumber(wxPayConfig.getMerchantSerialNumber())
.apiV3Key(wxPayConfig.getApiV3Key())
.build();
}catch (Exception e){
e.printStackTrace();
log.error("构建商户配置信息出错,错误信息为"+e.getMessage());
return null;
}
}
}
}
return instance;
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class WxPayVO {
private String orderId;
private Long rUserId;
/***
* 非登录状态下单金额
*/
private BigDecimal amount;
private String openid;
private Long venderId;
/**
* 微信支付附言信息 格式为 服务商名称|服务商id
*/
private String attach;
/***
* 服务商商户号
*/
private String subMchid;
/***
* 服务商appId
*/
private String subAppid;
}
4.相关支付和回调接口
private static AjaxResult getJsApiPay(WxPayVO wxPayVO, BigDecimal money) {
Config config = WxInitUtils.getInstance(wxPayConfig);
// --------------------------微信jsp下单部分----------------------
JsapiService service = new JsapiService.Builder().config(config).build();
PrepayRequest request = new PrepayRequest();
//初始化金额部分
Amount amount = new Amount();
//订单金额 分
amount.setTotal(money.intValue());
request.setAmount(amount);
//平台appId 服务商应用ID
request.setSpAppid(wxPayConfig.getAppId());
//服务商户号
request.setSpMchid(wxPayConfig.getMerchantId());
//子商户应用ID 可以不要
//request.setSubAppid("xxx");
//子商户号
request.setSubMchid(wxPayVO.getSubMchid());
//商品标题
request.setDescription("标题");
//商品下单时生成的订单号 微信回调返回的订单id
request.setOutTradeNo(wxPayVO.getOrderId());
//附言 备注部分
request.setAttach(wxPayVO.getAttach());
//通知地址 通知URL必须为直接可访问的URL,不允许携带查询串,要求必须为https地址。
//示例值:https://www.weixin.qq.com/wxpay/pay.php
request.setNotifyUrl(wxPayConfig.getNotifyUrl());
Payer payer = new Payer();
payer.setSpOpenid(wxPayVO.getOpenid());
request.setPayer(payer);
apiService = new JsapiServiceExtension.Builder()
.config(config)
.signType("RSA") // 不填默认为RSA
.build();
log.info(request.toString());
// ... 生成预下单prepayId 并进行签名验证 此部分返回值前端可开箱即用 如果支付显示签名失败 请查看appid是否正确
PrepayWithRequestPaymentResponse requestPaymentResponse = apiService.prepayWithRequestPayment(request, wxPayConfig.getAppId());
return AjaxResult.success(requestPaymentResponse);
}
@RequestMapping("callback/")
public AjaxResult callback(HttpServletRequest request, HttpServletResponse response) {
log.info("-------------------------------进入支付回调环节--------------------------------");
try {
//获取body参数
StringBuilder sb = new StringBuilder();
BufferedReader reader = request.getReader();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
String body = sb.toString();
// 从请求头中获取信息
String timestamp = request.getHeader("Wechatpay-Timestamp");
String nonce = request.getHeader("Wechatpay-Nonce");
String signature = request.getHeader("Wechatpay-Signature");
String singType = request.getHeader("Wechatpay-Signature-Type");
String serialNumber = request.getHeader("Wechatpay-Serial");
//微信内部解析参数类
RequestParam requestParam = new RequestParam.Builder()
.body(body)
.nonce(nonce)
.serialNumber(serialNumber)
.signature(signature)
.signType(singType)
.timestamp(timestamp)
.build();
//获取微信配置嘻戏
Config config = WxInitUtils.getInstance(wxPayConfig);
// 初始化解析器 NotificationParser
NotificationParser parser = new NotificationParser((NotificationConfig) config);
// 这个Transaction是微信包里面的 解码后的详细参数信息
Transaction transaction = parser.parse(requestParam, Transaction.class);
if ("SUCCESS".equals(transaction.getTradeState().name())) {
//支付成功相关订单错做
}
} catch (Exception e) {
log.error("支付回调解析失败----》》》》{}", e);
}
log.info("-------------------------------支付回调完成--------------------------------");
return AjaxResult.success();
}