使用weixin-java-pay实现微信小程序支付
准备工作
依赖引入
<dependency><groupId>com.github.binarywang</groupId><artifactId>weinxin-java-pay</artifactId><version>对应的版本号</version></dependency>
证书申请和下载
官方文档: 直达
撸起袖子使劲干
配置类
- 参数配置类
/**
* @author: Eden4J
* @Description: 微信支付商户信息配置类
*/@Data@Component@RefreshScope@ConfigurationProperties(prefix ="wechat.pay")publicclassWeChatPayProperties{/**
* 微信小程序或者微信公众号appId
*/privateString appid;/**
* 商户号
*/privateString mchId;/**
* 商户密钥
*/privateString mchKey;/**
* 商户证书序列号
*/privateString serialNo;/**
* apiV3Key
*/privateString apiV3Key;/**
* 证书
*/privateString keyPath;/**
* 商户私钥文件
*/privateString privateKeyPath;/**
* apiclient_cert.pem证书文件
*/privateString privateCertPath;/**
* 交易类型
* JSAPI--公众号支付
* NATIVE--原生扫码支付
* APP--app支付
*/privateString tradeType;/**
* 支付结果异步通知回调地址
*/privateString notifyUrl;}
- 微信支付配置类
/**
* @author: Eden4J
* @Description: 微信支付配置类
*/@Component@ConditionalOnClass(WxPayService.class)@RequiredArgsConstructorpublicclassWeChatPayConfig{privatefinalWeChatPayProperties properties;@Bean@ConditionalOnMissingBeanpublicWxPayConfigpayConfig(){WxPayConfig payConfig =newWxPayConfig();
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;}@BeanpublicWxPayServicewxPayService(WxPayConfig payConfig){WxPayService wxPayService =newWxPayServiceImpl();
wxPayService.setConfig(payConfig);return wxPayService;}}
- 自定义的微信预支付返回信息类
@DatapublicclassWxPayInfoVOimplementsSerializable{privateString appId;privateString timeStamp;privateString nonceStr;privateString packageValue;privateString signType;privateString paySign;}
工具类
/**
* @author: Eden4J
* @Description: 微信支付相关工具类
*/publicclassWxPayUtil{publicstaticStringsign(String signStr,PrivateKey privateKey){Sign sign =SecureUtil.sign(SignAlgorithm.SHA256withRSA, privateKey.getEncoded(),null);returnBase64.encode(sign.sign(signStr.getBytes()));}publicstaticStringbuildMessage(String appId,String timeStamp,String nonceStr,String body){return appId +"\n"+ timeStamp +"\n"+ nonceStr +"\n"+ body +"\n";}publicstaticAutoUpdateCertificatesVerifiergetVerifier(WxPayConfig wxPayConfig)throwsIOException{PrivateKey privateKey =PemUtils.loadPrivateKey(newClassPathResource("apiclient_key.pem").getInputStream());AutoUpdateCertificatesVerifier verifier =newAutoUpdateCertificatesVerifier(newWxPayCredentials(wxPayConfig.getMchId(),newPrivateKeySigner(wxPayConfig.getCertSerialNo(), privateKey)), wxPayConfig.getApiV3Key().getBytes("utf-8"));return verifier;}/**
* 验证签名
*
* @param certificate
* @param message
* @param signature
* @return
*/publicstaticbooleanverify(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){thrownewRuntimeException("当前Java环境不支持SHA256withRSA", e);}catch(SignatureException e){thrownewRuntimeException("签名验证过程发生了错误", e);}catch(InvalidKeyException e){thrownewRuntimeException("无效的证书", e);}}}
接口层和服务处理层代码
重点注意:微信支付回调结果通知不要使用JSONObject去做接收
- 接口层
@RestController@RequestMapping("/请求路径")@RequiredArgsConstructorpublicclassAppCustomerUserRechargeOrderController{privatefinalIAppCustomerUserRechargeOrderService rechargeOrderService;@PostMapping("/preOrder")publicResult<WxPayInfoVO>preOrder(@RequestParam("goodId")String goodId){returnResult.success(rechargeOrderService.preOrder(goodId));}// 支付回调@PostMapping("/back")publicMap<String,String>back(@RequestBodyMap body,HttpServletRequest request){return rechargeOrderService.formalOrder(body, request);}}
- 处理层
@OverridepublicWxPayInfoVOpreRecharge(String goodId){try{//看看是否有其他的业务逻辑// 调用微信的统一下单接口获取预支付单返回前端 createOrderV3(TradeTypeEnum tradeType, WxPayUnifiedOrderV3Request request)WxPayUnifiedOrderV3Request payRequest =newWxPayUnifiedOrderV3Request();
payRequest.setOutTradeNo(rechargeNo);//系统充值订单号
payRequest.setDescription(goodsPackage.getPackageName());//订单失效时间SimpleDateFormat dateFormat =newSimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
payRequest.setTimeExpire(dateFormat.format(DateUtil.offset(newDate(),DateField.HOUR_OF_DAY,1)));WxPayUnifiedOrderV3Request.Payer payer =newWxPayUnifiedOrderV3Request.Payer();
payer.setOpenid(userAccount.getOpenId());
payRequest.setPayer(payer);WxPayUnifiedOrderV3Request.Amount amount =newWxPayUnifiedOrderV3Request.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(newClassPathResource("apiclient_key.pem").getInputStream()));WxPayInfoVO payInfoVO =PojoUtil.exchangePojo(jsapiResult,WxPayInfoVO.class);
payInfoVO.setPaySign(encode);return payInfoVO;}catch(WxPayException e){
e.printStackTrace();thrownewBizException("微信支付失败", e);}catch(IOException e){
e.printStackTrace();thrownewBizException("微信支付失败", e);}}@OverridepublicMap<String,String>createFormalOrder(Map body,HttpServletRequest request){try{Map<String,String> resultMap =newHashMap<>();
resultMap.put("code","FAIL");ObjectMapper objectMapper =newObjectMapper();try{//官方文档中有说明切记不要改变原始报文主体,如果使用JSONObject接收的话,不能使用JSON转换出来的字符串,会出现验签错误的情况,请注意String data = objectMapper.writeValueAsString(body);SignatureHeader header =newSignatureHeader();
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();thrownewBizException("微信支付成功回调失败", e);}}
结束!
本文转载自: https://blog.csdn.net/qq_15090197/article/details/136938894
版权归原作者 Eden要努力搞钱 所有, 如有侵权,请联系我们删除。
版权归原作者 Eden要努力搞钱 所有, 如有侵权,请联系我们删除。