SpringBoot整合weixin-java-pay实现微信小程序支付
使用weixin-java-pay实现微信小程序支付
准备工作
依赖引入
com.github.binarywang weinxin-java-pay 对应的版本号
证书申请和下载
官方文档: 直达
撸起袖子使劲干
配置类
- 参数配置类
/**
* @author: Eden4J
* @Description: 微信支付商户信息配置类
*/
@Data
@Component
@RefreshScope
@ConfigurationProperties(prefix = "wechat.pay")
public class WeChatPayProperties {
/**
* 微信小程序或者微信公众号appId
*/
private String appid;
/**
* 商户号
*/
private String mchId;
/**
* 商户密钥
*/
private String mchKey;
/**
* 商户证书序列号
*/
private String serialNo;
/**
* apiV3Key
*/
private String apiV3Key;
/**
* 证书
*/
private String keyPath;
/**
* 商户私钥文件
*/
private String privateKeyPath;
/**
* apiclient_cert.pem证书文件
*/
private String privateCertPath;
/**
* 交易类型
* JSAPI--公众号支付
* NATIVE--原生扫码支付
* APP--app支付
*/
private String tradeType;
/**
* 支付结果异步通知回调地址
*/
private String notifyUrl;
}
- 微信支付配置类
/**
* @author: Eden4J
* @Description: 微信支付配置类
*/
@Component
@ConditionalOnClass(WxPayService.class)
@RequiredArgsConstructor
public class WeChatPayConfig {
private final WeChatPayProperties properties;
@Bean
@ConditionalOnMissingBean
public WxPayConfig payConfig() {
WxPayConfig payConfig = new WxPayConfig();
payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppid()));
payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
payConfig.setCertSerialNo(StringUtils.trimToNull(this.properties.getSerialNo()));
payConfig.setApiV3Key(StringUtils.trimToNull(this.properties.getApiV3Key()));
payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
payConfig.setPrivateKeyPath(StringUtils.trimToNull(this.properties.getPrivateKeyPath()));
payConfig.setPrivateCertPath(StringUtils.trimToNull(this.properties.getPrivateCertPath()));
payConfig.setTradeType(StringUtils.trimToNull(this.properties.getTradeType()));
return payConfig;
}
@Bean
public WxPayService wxPayService(WxPayConfig payConfig) {
WxPayService wxPayService = new WxPayServiceImpl();
wxPayService.setConfig(payConfig);
return wxPayService;
}
}
- 自定义的微信预支付返回信息类
@Data
public class WxPayInfoVO implements Serializable {
private String appId;
private String timeStamp;
private String nonceStr;
private String packageValue;
private String signType;
private String paySign;
}
工具类
/**
* @author: Eden4J
* @Description: 微信支付相关工具类
*/
public class WxPayUtil {
public static String sign(String signStr, PrivateKey privateKey) {
Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA, privateKey.getEncoded(), null);
return Base64.encode(sign.sign(signStr.getBytes()));
}
public static String buildMessage(String appId, String timeStamp, String nonceStr, String body) {
return appId + "\n" + timeStamp + "\n" + nonceStr + "\n" + body + "\n";
}
public static AutoUpdateCertificatesVerifier getVerifier(WxPayConfig wxPayConfig) throws IOException {
PrivateKey privateKey = PemUtils.loadPrivateKey(new ClassPathResource("apiclient_key.pem").getInputStream());
AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
new WxPayCredentials(wxPayConfig.getMchId(), new PrivateKeySigner(wxPayConfig.getCertSerialNo(), privateKey))
, wxPayConfig.getApiV3Key().getBytes("utf-8")
);
return verifier;
}
/**
* 验证签名
*
* @param certificate
* @param message
* @param signature
* @return
*/
public static boolean verify(AutoUpdateCertificatesVerifier certificate, byte[] message, String signature) {
try {
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initVerify(certificate.getValidCertificate());
sign.update(message);
return sign.verify(java.util.Base64.getDecoder().decode(signature));
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
} catch (SignatureException e) {
throw new RuntimeException("签名验证过程发生了错误", e);
} catch (InvalidKeyException e) {
throw new RuntimeException("无效的证书", e);
}
}
}
接口层和服务处理层代码
重点注意:微信支付回调结果通知不要使用JSONObject去做接收
- 接口层
@RestController
@RequestMapping("/请求路径")
@RequiredArgsConstructor
public class AppCustomerUserRechargeOrderController {
private final IAppCustomerUserRechargeOrderService rechargeOrderService;
@PostMapping("/preOrder")
public Result preOrder(@RequestParam("goodId") String goodId) {
return Result.success(rechargeOrderService.preOrder(goodId));
}
// 支付回调
@PostMapping("/back")
public Map back(@RequestBody Map body,HttpServletRequest request) {
return rechargeOrderService.formalOrder(body, request);
}
}
- 处理层
@Override
public WxPayInfoVO preRecharge(String goodId) {
try {
//看看是否有其他的业务逻辑
// 调用微信的统一下单接口获取预支付单返回前端 createOrderV3(TradeTypeEnum tradeType, WxPayUnifiedOrderV3Request request)
WxPayUnifiedOrderV3Request payRequest = new WxPayUnifiedOrderV3Request();
payRequest.setOutTradeNo(rechargeNo);//系统充值订单号
payRequest.setDescription(goodsPackage.getPackageName());
//订单失效时间
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
payRequest.setTimeExpire(dateFormat.format(DateUtil.offset(new Date(), DateField.HOUR_OF_DAY, 1)));
WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
payer.setOpenid(userAccount.getOpenId());
payRequest.setPayer(payer);
WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
amount.setTotal(rechargeOrder.getTotalAmount().multiply(BigDecimal.valueOf(100)).intValue());
amount.setCurrency("CNY");
payRequest.setAmount(amount);
payRequest.setNotifyUrl(weChatPayProperties.getNotifyUrl());
WxPayUnifiedOrderV3Result.JsapiResult jsapiResult = wxPayService.createOrderV3(TradeTypeEnum.JSAPI, payRequest);
String encode = WxPayUtil.sign(WxPayUtil.buildMessage(weChatPayProperties.getAppid(), jsapiResult.getTimeStamp(), jsapiResult.getNonceStr(), jsapiResult.getPackageValue())
, PemUtils.loadPrivateKey(new ClassPathResource("apiclient_key.pem").getInputStream()));
WxPayInfoVO payInfoVO = PojoUtil.exchangePojo(jsapiResult, WxPayInfoVO.class);
payInfoVO.setPaySign(encode);
return payInfoVO;
} catch (WxPayException e) {
e.printStackTrace();
throw new BizException("微信支付失败", e);
} catch (IOException e) {
e.printStackTrace();
throw new BizException("微信支付失败", e);
}
}
@Override
public Map createFormalOrder(Map body, HttpServletRequest request) {
try {
Map resultMap = new HashMap();
resultMap.put("code", "FAIL");
ObjectMapper objectMapper = new ObjectMapper();
try {
//官方文档中有说明切记不要改变原始报文主体,如果使用JSONObject接收的话,不能使用JSON转换出来的字符串,会出现验签错误的情况,请注意
String data = objectMapper.writeValueAsString(body);
SignatureHeader header = new SignatureHeader();
header.setTimeStamp(request.getHeader("Wechatpay-Timestamp"));
header.setNonce(request.getHeader("Wechatpay-Nonce"));
header.setSignature(request.getHeader("Wechatpay-Signature"));
header.setSerial(request.getHeader("Wechatpay-Serial"));
WxPayNotifyV3Result notifyV3Result =wxPayService.parseOrderNotifyV3Result(data, header);
WxPayNotifyV3Result.DecryptNotifyResult decryptNotifyResult = notifyV3Result.getResult();//解密后的数据
if ("SUCCESS".equalsIgnoreCase(decryptNotifyResult.getTradeState())) {
resultMap.put("code", "SUCCESS");
}
} catch (Exception e) {
e.printStackTrace();
}
return resultMap;
} catch (Exception e) {
e.printStackTrace();
throw new BizException("微信支付成功回调失败", e);
}
}
结束!
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

