java對接微信支付SDK接口簡單圖文教程
1.對接準備
需要的參數包括開發(fā)者ID(appid)、商戶號、商戶api私鑰、商戶證書序列號、商戶APIV3密鑰、回調地址。
在微信公眾平臺https://mp.weixin.qq.com/ 注冊應用,類型只選擇“公眾號/小程序/企業(yè)微信”,注冊完成后需完成”微信認證“(微信收取300元),在基礎配置中拿到開發(fā)者ID(APPID)。
在微信支付商戶平臺https://pay.weixin.qq.com注冊商戶,在賬戶中心-api安全中設置APIv3密鑰,微信支付 APIv3 使用由 證書授權機構(Certificate Authority,簡稱CA)簽發(fā)的證書,商戶申請證書時,證書工具會生成商戶私鑰,并保存在本地證書文件夾的件 apiclient_key.pem
中。開發(fā)和部署,需要區(qū)分環(huán)境,加載 apiclient_key.pem
文件。
在賬戶中心-商戶信息中拿到微信支付商戶號,即商戶ID (收錢的商家ID);
在產品中心-appid賬號管理中,將申請的下來的APPID綁定到商戶號下。
Certificate Downloader 是 Java 微信支付 APIv3 平臺證書的命令行下載工具。該工具可從https://api.mch.weixin.qq.com/v3/certificates
接口獲取商戶可用證書。
2.maven引入jar包
<!-- 微信支付SDK --> <dependency> <groupId>com.github.wechatpay-apiv3</groupId> <artifactId>wechatpay-java</artifactId> <version>0.2.9</version> </dependency>
3.yml文件配置微信參數,工具類讀取
@Component public class WechatPayConfig { /** * 應用ID */ public static String appid; /** * 商戶號 */ public static String merchantId; /** * 商戶API私鑰路徑 */ public static String privateKeyPath; /** * 商戶證書序列號 */ public static String merchantSerialNumber; /** * 商戶APIV3密鑰 */ public static String apiV3Key; /** * 通知地址(有效性:1. HTTPS;2. 不允許攜帶查詢串。) */ public static String notifyUrl; /** * 微信支付配置 */ public static Config config; /** * 訂單支付超時時間/分鐘 */ public static final Integer ORDER_PAY_TIME_OUT = 1440; private WechatPayConfig() {} @Value("${wechat.pay.appid}") public void setAppid(String appid) { WechatPayConfig.appid = appid; } @Value("${wechat.pay.merchantId}") public void setMerchantId(String merchantId) { WechatPayConfig.merchantId = merchantId; } @Value("${wechat.pay.privateKeyPath}") public void setPrivateKeyPath(String privateKeyPath) { String classPath = System.getProperty("java.class.path"); // 是否運行在開發(fā)環(huán)境 boolean isRunningFromIde = classPath.toLowerCase().contains("eclipse") || classPath.toLowerCase().contains("idea"); // 開發(fā)環(huán)境與部署jar包環(huán)境 不同獲取私鑰路徑 if (isRunningFromIde){ WechatPayConfig.privateKeyPath = getClass().getClassLoader().getResource("apiclient_key.pem").getPath(); }else { WechatPayConfig.privateKeyPath = privateKeyPath; } } @Value("${wechat.pay.merchantSerialNumber}") public void setMerchantSerialNumber(String merchantSerialNumber) { WechatPayConfig.merchantSerialNumber = merchantSerialNumber; } @Value("${wechat.pay.apiV3Key}") public void setApiV3Key(String apiV3Key) { WechatPayConfig.apiV3Key = apiV3Key; } @Value("${wechat.pay.notifyUrl}") public void setNotifyUrl(String notifyUrl) { WechatPayConfig.notifyUrl = notifyUrl; } @PostConstruct public void initializeConfig() { // 初始化微信配置 config = new RSAAutoCertificateConfig.Builder() .merchantId(merchantId) .privateKeyFromPath(privateKeyPath) .merchantSerialNumber(merchantSerialNumber) .apiV3Key(apiV3Key) .build(); } }
4.對接支付接口
/** * 微信 Native 支付下單 * * @param amt 金額 * @param orderNumber 訂單號 * @param description 描述 * @return 二維碼鏈接 */ public static AjaxResult nativePay(BigDecimal amt, String orderNumber, String description) { // 當前時間 Date currentDate = new Date(); // 將金額轉換為分 int total = amt.multiply(new BigDecimal("100")).intValue(); try { // 構建service NativePayService service = new NativePayService.Builder().config(WechatPayConfig.config).build(); // 構建請求對象 PrepayRequest request = new PrepayRequest(); request.setAppid(WechatPayConfig.appid); request.setMchid(WechatPayConfig.merchantId); request.setNotifyUrl(WechatPayConfig.notifyUrl); // 設置金額 Amount amount = new Amount(); amount.setTotal(total); request.setAmount(amount); request.setDescription(description); request.setOutTradeNo(orderNumber); // 計算訂單失效時間 Calendar calendar = DateUtils.toCalendar(currentDate); calendar.add(Calendar.MINUTE, WechatPayConfig.ORDER_PAY_TIME_OUT); request.setTimeExpire(DateUtils.parseDateToStr("yyyy-MM-dd'T'HH:mm:ss+08:00", calendar.getTime())); return AjaxResult.success(service.prepay(request).getCodeUrl()); } catch (Exception e){ log.error(e.getMessage(),e); return AjaxResult.error("支付訂單創(chuàng)建失敗"); } }
5.回調地址
/** * 微信支付回調 * * @return 回調結果 */ @PostMapping("/wechat") public ResponseEntity.BodyBuilder wechat(@RequestBody String body, HttpServletRequest request) { try { // 構造 RequestParam RequestParam requestParam = new RequestParam.Builder() // 序列號 .serialNumber(request.getHeader("Wechatpay-Serial")) // 隨機數 .nonce(request.getHeader("Wechatpay-Nonce")) // 簽名 .signature(request.getHeader("Wechatpay-Signature")) // 時間戳 .timestamp(request.getHeader("Wechatpay-Timestamp")) .body(body) .build(); // 初始化解析器 NotificationParser parser = new NotificationParser((NotificationConfig) WechatPayConfig.config); // 驗簽、解密并轉換成 Transaction Transaction transaction = parser.parse(requestParam, Transaction.class); // 校驗交易狀態(tài) if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) { // 支付成功,根據訂單編號查詢訂單信息 // 1.查詢訂單信息 Order orderOld = orderService.selectForUpdateByOrderNumber(transaction.getOutTradeNo()); // 校驗金額 if (orderOld != null && orderOld.getPayAmount().equals(transaction.getAmount().getTotal())) { // 金額相等 完成支付 更新訂單狀態(tài) WechatPayUtil.success(orderOld,transaction); } else { // 金額異常 執(zhí)行退款 WechatPayUtil.refunded(new WechatPayRedis(transaction.getOutTradeNo(), transaction.getAmount().getTotal(), null)); } } } catch (ValidationException e) { // 簽名驗證失敗,返回 401 UNAUTHORIZED 狀態(tài)碼 return ResponseEntity.status(HttpStatus.UNAUTHORIZED); } // 處理成功,返回 200 OK 狀態(tài)碼 return ResponseEntity.status(HttpStatus.OK); } /** * 支付成功 */ public static void success( Order orderOld,Transaction transaction) { try { // 支付完成時間 Date payTime = DateUtils.parseDate(transaction.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ss+08:00"); // 校驗訂單信息 & 支付結果 & 訂單有效期止日期 if (orderOld != null && orderOld.getPayResult() == 0 && payTime.compareTo(orderOld.getExpirationDate()) < 1) { // 構建修改對象 Order updateOrder = new Order(); updateOrder.setId(orderOld.getId()); updateOrder.setPayMethod(PayMethodEnum.W.name()); updateOrder.setPayChannel(PayChannelEnum.P.name()); updateOrder.setPayDate(payTime); updateOrder.setPayResult(PayResultEnum.PAID.getCode()); updateOrder.setPayType(PayTypeEnum.U.name()); updateOrder.setSerialNumber(transaction.getTransactionId()); if (orderService.editPayResult(updateOrder,orderOld) == 1) { // 刪除Redis訂單支付信息 SpringUtils.getBean(RedisCache.class).deleteObject(WechatPayConfig.ORDER_PAY_REDIS_PREFIX + transaction.getOutTradeNo()); } } else { // 訂單信息不存在 執(zhí)行退款 WechatPayUtil.refunded(new WechatPayRedis(transaction.getOutTradeNo(), transaction.getAmount().getTotal(), null)); } } catch (Exception e) { log.error(e.getMessage(), e); } } /** * 執(zhí)行退款 */ public static void refunded(WechatPayRedis wechatPay) { try { // 構建退款Service RefundService service = new RefundService.Builder().config(WechatPayConfig.config).build(); // 構建請求對象 CreateRequest request = new CreateRequest(); request.setOutTradeNo(wechatPay.getOrderNumber()); request.setOutRefundNo(wechatPay.getOrderNumber()); // 支付總金額(分) long total = wechatPay.getTotal(); // 設置退款金額 AmountReq amount = new AmountReq(); amount.setRefund(total); amount.setTotal(total); amount.setCurrency("CNY"); request.setAmount(amount); // 請求API申請退款 Refund refund = service.create(request); // 校驗退款結果 if (refund != null && Status.SUCCESS.equals(refund.getStatus())) { // 退款成功 log.info("微信退款成功:{}", wechatPay); } } catch (Exception e) { log.error(e.getMessage(), e); } }
總結
到此這篇關于java對接微信支付SDK接口的文章就介紹到這了,更多相關java對接微信支付SDK接口內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java 如何實現POST(x-www-form-urlencoded)請求
這篇文章主要介紹了Java 實現POST(x-www-form-urlencoded)請求,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10