SpringBoot整合weixin-java-pay實(shí)現(xiàn)微信小程序支付的示例代碼
準(zhǔn)備工作
依賴引入
<dependency> <groupId>com.github.binarywang</groupId> <artifactId>weinxin-java-pay</artifactId> <version>對應(yīng)的版本號(hào)</version> </dependency>
證書申請和下載
官方文檔: 直達(dá)
擼起袖子使勁干
配置類
參數(shù)配置類
/** * @author: Eden4J * @Description: 微信支付商戶信息配置類 */ @Data @Component @RefreshScope @ConfigurationProperties(prefix = "wechat.pay") public class WeChatPayProperties { /** * 微信小程序或者微信公眾號(hào)appId */ private String appid; /** * 商戶號(hào) */ private String mchId; /** * 商戶密鑰 */ private String mchKey; /** * 商戶證書序列號(hào) */ private String serialNo; /** * apiV3Key */ private String apiV3Key; /** * 證書 */ private String keyPath; /** * 商戶私鑰文件 */ private String privateKeyPath; /** * apiclient_cert.pem證書文件 */ private String privateCertPath; /** * 交易類型 * JSAPI--公眾號(hào)支付 * NATIVE--原生掃碼支付 * APP--app支付 */ private String tradeType; /** * 支付結(jié)果異步通知回調(diào)地址 */ 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; } }
自定義的微信預(yù)支付返回信息類
@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: 微信支付相關(guān)工具類 */ 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; } /** * 驗(yàn)證簽名 * * @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("當(dāng)前Java環(huán)境不支持SHA256withRSA", e); } catch (SignatureException e) { throw new RuntimeException("簽名驗(yàn)證過程發(fā)生了錯(cuò)誤", e); } catch (InvalidKeyException e) { throw new RuntimeException("無效的證書", e); } } }
接口層和服務(wù)處理層代碼
重點(diǎn)注意:微信支付回調(diào)結(jié)果通知不要使用JSONObject去做接收
接口層
@RestController @RequestMapping("/請求路徑") @RequiredArgsConstructor public class AppCustomerUserRechargeOrderController { private final IAppCustomerUserRechargeOrderService rechargeOrderService; @PostMapping("/preOrder") public Result<WxPayInfoVO> preOrder(@RequestParam("goodId") String goodId) { return Result.success(rechargeOrderService.preOrder(goodId)); } // 支付回調(diào) @PostMapping("/back") public Map<String,String> back(@RequestBody Map body,HttpServletRequest request) { return rechargeOrderService.formalOrder(body, request); } }
處理層
@Override public WxPayInfoVO preRecharge(String goodId) { try { //看看是否有其他的業(yè)務(wù)邏輯 // 調(diào)用微信的統(tǒng)一下單接口獲取預(yù)支付單返回前端 createOrderV3(TradeTypeEnum tradeType, WxPayUnifiedOrderV3Request request) WxPayUnifiedOrderV3Request payRequest = new WxPayUnifiedOrderV3Request(); payRequest.setOutTradeNo(rechargeNo);//系統(tǒng)充值訂單號(hào) payRequest.setDescription(goodsPackage.getPackageName()); //訂單失效時(shí)間 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<String, String> createFormalOrder(Map body, HttpServletRequest request) { try { Map<String, String> resultMap = new HashMap<>(); resultMap.put("code", "FAIL"); ObjectMapper objectMapper = new ObjectMapper(); try { //官方文檔中有說明切記不要改變原始報(bào)文主體,如果使用JSONObject接收的話,不能使用JSON轉(zhuǎn)換出來的字符串,會(huì)出現(xiàn)驗(yàn)簽錯(cuò)誤的情況,請注意 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();//解密后的數(shù)據(jù) if ("SUCCESS".equalsIgnoreCase(decryptNotifyResult.getTradeState())) { resultMap.put("code", "SUCCESS"); } } catch (Exception e) { e.printStackTrace(); } return resultMap; } catch (Exception e) { e.printStackTrace(); throw new BizException("微信支付成功回調(diào)失敗", e); } }
到此這篇關(guān)于SpringBoot整合weixin-java-pay實(shí)現(xiàn)微信小程序支付的示例代碼的文章就介紹到這了,更多相關(guān)SpringBoot weixin-java-pay微信小程序支付內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JetBrains IntelliJ IDEA 優(yōu)化教超詳細(xì)程
這篇文章主要介紹了JetBrains IntelliJ IDEA 優(yōu)化教超詳細(xì)程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03SpringBoot基于RabbitMQ實(shí)現(xiàn)消息延時(shí)隊(duì)列的方案
在很多的業(yè)務(wù)場景中,延時(shí)隊(duì)列可以實(shí)現(xiàn)很多功能,此類業(yè)務(wù)中,一般上是非實(shí)時(shí)的,需要延遲處理的,需要進(jìn)行重試補(bǔ)償?shù)?本文給大家介紹了SpringBoot基于RabbitMQ實(shí)現(xiàn)消息延遲隊(duì)列的方案,文中有詳細(xì)的代碼講解,需要的朋友可以參考下2024-04-04解決BufferedReader.readLine()遇見的坑
這篇文章主要介紹了解決BufferedReader.readLine()遇見的坑,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java8新特性lambda表達(dá)式有什么用(用法實(shí)例)
這篇文章主要介紹了Java8新特性lambda表達(dá)式有什么用,著重以實(shí)例講解lambda表達(dá)式,需要的朋友可以參考下2014-06-06在Spring Boot中處理文件上傳功能實(shí)現(xiàn)
這篇文章主要介紹了如何在Spring Boot中處理文件上傳,通過配置文件上傳屬性、創(chuàng)建控制器來處理上傳的文件,并通過異常處理器來管理錯(cuò)誤情況,可以快速實(shí)現(xiàn)文件上傳功能,需要的朋友可以參考下2024-06-06