最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot整合weixin-java-pay實(shí)現(xiàn)微信小程序支付的示例代碼

 更新時(shí)間:2024年05月31日 11:26:52   作者:Eden要努力搞錢(qián)  
微信小程序支付是常見(jiàn)的一種功能,本文主要介紹了SpringBoot整合weixin-java-pay實(shí)現(xiàn)微信小程序支付的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

準(zhǔn)備工作

依賴引入

<dependency>
  <groupId>com.github.binarywang</groupId>
  <artifactId>weinxin-java-pay</artifactId>
  <version>對(duì)應(yīng)的版本號(hào)</version>
</dependency>

證書(shū)申請(qǐng)和下載

官方文檔: 直達(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;
    /**
     * 商戶證書(shū)序列號(hào)
     */
    private String serialNo;
    /**
     * apiV3Key
     */
    private String apiV3Key;
    /**
     * 證書(shū)
     */
    private String keyPath;
    /**
     * 商戶私鑰文件
     */
    private String privateKeyPath;

    /**
     * apiclient_cert.pem證書(shū)文件
     */
    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)證過(guò)程發(fā)生了錯(cuò)誤", e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("無(wú)效的證書(shū)", e);
        }
    }
}

接口層和服務(wù)處理層代碼

重點(diǎn)注意:微信支付回調(diào)結(jié)果通知不要使用JSONObject去做接收

接口層

@RestController
@RequestMapping("/請(qǐng)求路徑")
@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 {
            	//官方文檔中有說(shuō)明切記不要改變?cè)紙?bào)文主體,如果使用JSONObject接收的話,不能使用JSON轉(zhuǎn)換出來(lái)的字符串,會(huì)出現(xiàn)驗(yàn)簽錯(cuò)誤的情況,請(qǐng)注意
                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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中的FileInputStream是否需要close問(wèn)題

    Java中的FileInputStream是否需要close問(wèn)題

    這篇文章主要介紹了Java中的FileInputStream是否需要close問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 基于Java編寫(xiě)第一個(gè)區(qū)塊鏈項(xiàng)目

    基于Java編寫(xiě)第一個(gè)區(qū)塊鏈項(xiàng)目

    區(qū)塊鏈?zhǔn)欠植际綌?shù)據(jù)存儲(chǔ)、點(diǎn)對(duì)點(diǎn)傳輸、共識(shí)機(jī)制、加密算法等計(jì)算機(jī)技術(shù)的新型應(yīng)用模式,下面這篇文章主要給大家介紹了基于Java實(shí)現(xiàn)區(qū)塊鏈的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • CompletableFuture?異步編排示例詳解

    CompletableFuture?異步編排示例詳解

    這篇文章主要為大家介紹了CompletableFuture?異步編排示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 通過(guò)Java計(jì)算文件的MD5值實(shí)現(xiàn)方式

    通過(guò)Java計(jì)算文件的MD5值實(shí)現(xiàn)方式

    本文將詳細(xì)介紹如何使用Java語(yǔ)言來(lái)計(jì)算文件的MD5值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • shade解決mybatis包沖突問(wèn)題及項(xiàng)目引用的方法

    shade解決mybatis包沖突問(wèn)題及項(xiàng)目引用的方法

    這篇文章主要介紹了shade解決mybatis包沖突問(wèn)題及項(xiàng)目引用的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • redis深入淺出分布式鎖實(shí)現(xiàn)上篇

    redis深入淺出分布式鎖實(shí)現(xiàn)上篇

    在單體應(yīng)用中,如果我們對(duì)共享數(shù)據(jù)不進(jìn)行加鎖操作,會(huì)出現(xiàn)數(shù)據(jù)一致性問(wèn)題,我們的解決辦法通常是加鎖。下面我們一起聊聊使用redis來(lái)實(shí)現(xiàn)分布式鎖
    2022-08-08
  • SpringBoot整合RocketMq實(shí)現(xiàn)分布式事務(wù)

    SpringBoot整合RocketMq實(shí)現(xiàn)分布式事務(wù)

    這篇文章主要為大家詳細(xì)介紹了SpringBoot整合RocketMq實(shí)現(xiàn)分布式事務(wù)的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),有需要的小伙伴可以參考一下
    2024-11-11
  • java的json解析類庫(kù)使用示例

    java的json解析類庫(kù)使用示例

    這篇文章主要介紹了java的json解析類庫(kù)使用方法,這里使用Zson解析json,這是一個(gè)開(kāi)源的json處理類庫(kù)
    2014-03-03
  • SpringBoot+React實(shí)現(xiàn)計(jì)算個(gè)人所得稅

    SpringBoot+React實(shí)現(xiàn)計(jì)算個(gè)人所得稅

    本文將以個(gè)人所得稅的計(jì)算為例,使用React+SpringBoot+GcExcel來(lái)實(shí)現(xiàn)這一功能,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解下
    2023-09-09
  • Java實(shí)現(xiàn)ThreadLocal數(shù)據(jù)在線程池間傳遞的解決方案

    Java實(shí)現(xiàn)ThreadLocal數(shù)據(jù)在線程池間傳遞的解決方案

    隨著業(yè)務(wù)的發(fā)展,系統(tǒng)新增了一個(gè)需求:需要根據(jù)接口請(qǐng)求頭中的特定信息動(dòng)態(tài)選擇數(shù)據(jù)庫(kù)實(shí)例進(jìn)行查詢,這個(gè)上下文信息在請(qǐng)求進(jìn)入后被存儲(chǔ)在ThreadLocal中,本文給大家介紹了Java實(shí)現(xiàn)ThreadLocal數(shù)據(jù)在線程池間傳遞的解決方案,需要的朋友可以參考下
    2025-07-07

最新評(píng)論

兴义市| 手机| 乌兰察布市| 阿克苏市| 柏乡县| 松江区| 垣曲县| 临西县| 安平县| 图木舒克市| 宣汉县| 莲花县| 太谷县| 海兴县| 平塘县| 商城县| 温州市| 成安县| 天柱县| 营山县| 柘荣县| 武强县| 天峨县| 桐乡市| 亚东县| 韶关市| 平顺县| 桃江县| 丰宁| 都兰县| 新建县| 罗平县| 玉屏| 兴安县| 阿勒泰市| 远安县| 米林县| 浦东新区| 大邑县| 买车| 奉化市|