赞
踩
我用的是微信官方推荐的java版本的SDK,maven坐标如下
- <dependency>
- <groupId>com.github.wechatpay-apiv3</groupId>
- <artifactId>wechatpay-java</artifactId>
- <version>0.2.12</version>
- </dependency>
xxx: pay: wechat-pay: #商户号 merchantId: xxxxxxx #商户API私钥(很长) privateKey: xxxxxxx... #商户API公钥 (也很长) publicKey: xxxxxx.... #微信支付的商户平台证书序列号 merchantSerialNo: xxxxxxxxxxx #微信公众号ID appid: xxxxxxxxx #支付回调地址,必须是外网可访问的,文中会提供对应工具 notify_url: https://xxxxx #支付回调地址,同上,我写成了两个接口分开处理业务 refunds_notify_url: https://xxxxxxx #秘钥, 申请微信支付商户平台证书的时候能看见 apiV3Key: xxxxxxx #域名 domain: https://api.mch.weixin.qq.com
商户api证书:
申请完成之后商户api证书会下载成压缩包,解压之后就是上图的文件了,其中apiclient_key.pem就是商户私钥, 另外一个就是公钥了,具体都是做什么的可以去看官网或者其他文章
- import com.wechat.pay.java.core.Config;
- import com.wechat.pay.java.core.RSAAutoCertificateConfig;
- import com.wechat.pay.java.service.billdownload.BillDownloadServiceExtension;
- import com.wechat.pay.java.service.payments.app.AppServiceExtension;
- import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
- import com.wechat.pay.java.service.refund.RefundService;
- import lombok.Data;
- import lombok.NoArgsConstructor;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.core.annotation.Order;
-
- import java.security.KeyFactory;
- import java.security.NoSuchAlgorithmException;
- import java.security.PrivateKey;
- import java.security.spec.InvalidKeySpecException;
- import java.security.spec.PKCS8EncodedKeySpec;
- import java.util.Base64;
- import java.util.List;
-
- /**
- * @author: wxj
- * @Desc:
- * @create: 2023-11-06 13:15:34
- **/
-
- @Data
- @Configuration
- @NoArgsConstructor
- public class WechatPayConfig {
- @Value("${}")
- private String merchantId;
- @Value("${}")
- private String privateKey;
- @Value("${}")
- private String publicKey;
- @Value("${}")
- private String serialNo;
- @Value("${}")
- private String appid;
- @Value("${}")
- private String notifyUrl;
- @Value("${}")
- private String apiV3Key;
- @Value("${}")
- private String domain;
- @Value("${}")
- private String refundNotifyUrl;
-
-
- /**
- * 初始化最基础的商户配置
- *
- * @return Config
- */
- @Bean
- @Order(0)
- public Config initConfig() {
- return new RSAAutoCertificateConfig.Builder()
- .merchantId(merchantId)
- .privateKey(privateKey)
- .merchantSerialNumber(serialNo)
- .apiV3Key(apiV3Key)
- .build();
- }
-
- /**
- * 初始化小程序需要的SDK支持服务
- *
- * @return JsapiService
- */
- @Bean
- @Order(1)
- public JsapiServiceExtension initJsapiService() {
- Config config = SpringUtils.getBean(Config.class);
- return new JsapiServiceExtension.Builder().config(config).build();
- }
-
- /**
- * 初始化安卓app需要的SDK支持服务
- *
- * @return AppService
- */
- @Bean
- @Order(2)
- public AppServiceExtension initAppService() {
- Config config = SpringUtils.getBean(Config.class);
- return new AppServiceExtension.Builder().config(config).build();
- }
-
- /**
- * 初始化退款服务需要的SDK支持服务
- *
- * @return RefundService
- */
- @Bean
- @Order(3)
- public RefundService initRefundService() {
- Config config = SpringUtils.getBean(Config.class);
- return new RefundService.Builder().config(config).build();
- }
-
- @Bean
- @Order(4)
- public BillDownloadServiceExtension initBillDownloadServiceExtension() {
- Config config = SpringUtils.getBean(Config.class);
- return new BillDownloadServiceExtension.Builder().config(config).build();
- }
- /**
- * 加载私钥
- */
- public PrivateKey getPrivateKey() {
- try {
- KeyFactory kf = KeyFactory.getInstance("RSA");
- return kf.generatePrivate(
- new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("当前Java环境不支持RSA", e);
- } catch (InvalidKeySpecException e) {
- throw new RuntimeException("无效的密钥格式");
- } catch (Exception e) {
- throw new RuntimeException("加载私钥异常,请检查私钥文件", e);
- }
- }
-
-
- }
- import cn.hutool.core.date.DateUtil;
- import com.alibaba.fastjson2.JSONObject;
- import com.wechat.pay.java.core.Config;
- import com.wechat.pay.java.core.exception.ValidationException;
- import com.wechat.pay.java.core.notification.NotificationConfig;
- import com.wechat.pay.java.core.notification.NotificationParser;
- import com.wechat.pay.java.core.notification.RequestParam;
- import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
- import com.wechat.pay.java.service.payments.jsapi.model.*;
- import com.wechat.pay.java.service.payments.model.Transaction;
- import com.wechat.pay.java.service.refund.RefundService;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.stereotype.Component;
- import org.springframework.transaction.annotation.Transactional;
-
- import javax.annotation.Resource;
- import javax.servlet.http.HttpServletRequest;
- import java.util.List;
- import java.util.concurrent.locks.ReentrantLock;
- import java.util.stream.Collectors;
-
- @Slf4j
- @Component
- public class WechatAppletPayService {
- @Resource
- private Config config;
- @Resource
- private JsapiServiceExtension jsapiService;
- @Resource
- private RefundService refundService;
- @Resource
- private WechatPayConfig payConfig;
- private final ReentrantLock lock = new ReentrantLock();
-
- /**
- * 创建订单
- *
- * @param orderBo 订单参数对象
- * @return
- */
- public R<PrepayWithRequestPaymentResponse> createOrder(CourseOrderBo orderBo) {
-
- // 创建未支付订单对象并插入数据库, 具体根据需求实现
- // Order 创建的订单对象 cusWechat用户在咱们小程序对应的对象, 主要需要用户的openId,openId是某个微信用户在第一次进小程序的时候就分配的唯一ID,不会变,还是不知道openId是啥的去百度搜吧
- return this.pushOrder(order, cusWechat);
- }
-
- /**
- * 拉起支付
- *
- * @param orderBo
- * @param cusWechat
- * @return
- */
- public R<PrepayWithRequestPaymentResponse> pushOrder(CourseOrderBo orderBo, CusWechat cusWechat) {
- String appid = cusWechat.getAppid();
- String openid = cusWechat.getOpenid();
-
- PrepayRequest request = new PrepayRequest();
- request.setMchid(payConfig.getMerchantId());
- request.setAppid(appid);
- request.setDescription(orderBo.getGoodsName());
- request.setOutTradeNo(orderBo.getOrderId());
- // 2023-11-30T15:45:48+08:00
- String timeExpire = DateUtil.offsetMinute(DateUtil.date(), 10).toString().replace(" ", "T") + "+08:00";
- request.setTimeExpire(timeExpire);
- JSONObject attach = new JSONObject(1);
- attach.put("couponCode", orderBo.getCouponCode());
- request.setAttach(attach.toString());
- request.setNotifyUrl(String.format(payConfig.getNotifyUrl(), WechatConstants.SourcePathEnum.PAY_FROM_APPLET));
- Amount amount = new Amount();
- amount.setTotal(orderBo.getTotalAmount().intValue());
- amount.setCurrency("CNY");
- request.setAmount(amount);
- Payer payer = new Payer();
- payer.setOpenid(openid);
- request.setPayer(payer);
- PrepayWithRequestPaymentResponse prepay = jsapiService.prepayWithRequestPayment(request);
- return R.ok(prepay);
- }
-
- /**
- * 通过微信交易ID查询订单
- *
- * @param id
- * @param transactionId
- * @return
- */
- public R getOrderByTransactionId(Long id, String transactionId) {
- QueryOrderByIdRequest request = new QueryOrderByIdRequest();
- request.setMchid(payConfig.getMerchantId());
- request.setTransactionId(transactionId);
- Transaction transactionResp = jsapiService.queryOrderById(request);
- Transaction.TradeStateEnum tradeState = transactionResp.getTradeState();
- CourseTransactionVo transactionVo = transactionService.queryById(id);
-
- }
-
- public R getOrderByOrderId(String orderId) {
- QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
- request.setMchid(payConfig.getMerchantId());
- request.setOutTradeNo(orderId);
- Transaction transactionResp = jsapiService.queryOrderByOutTradeNo(request);
- String appid = transactionResp.getAppid();
- String openId = transactionResp.getPayer().getOpenid();
- Long aLong = transactionResp.getAmount().getTotal().longValue();
- Long aLong1 = transactionResp.getAmount().getPayerTotal().longValue();
- String transactionId = transactionResp.getTransactionId();
- Transaction.TradeStateEnum tradeState = transactionResp.getTradeState();
- // 具体业务自行处理
- return R.ok();
- }
-
- @Transactional(rollbackFor = Exception.class)
- public R<String> closeOrder(String orderId) {
- try {
- CloseOrderRequest request = new CloseOrderRequest();
- request.setMchid(payConfig.getMerchantId());
- request.setOutTradeNo(orderId);
- jsapiService.closeOrder(request);
- // 具体业务自行处理
- return R.ok();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- }
这里包含了下单,根据商户订单号查询微信支付订单,根据微信支付订单号查询微信支付订单以及关闭订单四个接口,具体业务代码需要兄弟你自己根据你们项目需求写.
- import cn.hutool.core.util.EnumUtil;
- import com.wechat.pay.java.service.refund.RefundService;
- import com.wechat.pay.java.service.refund.model.*;
- import org.springframework.stereotype.Service;
-
- import javax.annotation.Resource;
-
- /**
- * @author: wxj
- * @Desc: 微信支付退款服务类
- * @create: 2023-12-06 17:17:33
- **/
-
- @Service
- public class WechatRefundService {
-
- @Resource
- private WechatPayConfig payConfig;
- @Resource
- private RefundService refundService;
-
- /**
- * 后台向微信支付申请退款
- *
- * @param bo 参数对象
- * orderId 退款的订单ID
- * refundAmount 实际退款金额(由相关人员与客户商谈)
- * refundReason 退款理由
- * @return 处理结果
- */
- public R<String> refundsOrder(CourseOrderBo bo) {
- try {
- // 具体业务自行实现
- CreateRequest request = new CreateRequest();
- request.setReason(reasonEnum.getReason());
- Integer platform = order.getPlatform();
- WechatConstants.PlatformEnum platformEnum = EnumUtil.likeValueOf(WechatConstants.PlatformEnum.class, platform);
- AmountReq amount = new AmountReq();
- amount.setRefund(refundAmount);
- amount.setTotal(order.getTotalAmount());
- amount.setCurrency("CNY");
- request.setAmount(amount);
- request.setOutRefundNo(refundTransaction.getId().toString());
- request.setOutTradeNo(orderId);
- Refund refund = refundService.create(request);
-
- Status status_wx = refund.getStatus();
-
- String refundId_wx = refund.getRefundId();
- String transactionId_wx = refund.getTransactionId();
- String orderId_wx = refund.getOutTradeNo();
- com.wechat.pay.java.service.refund.model.Amount amount_wx = refund.getAmount();
- long total_wx = amount_wx.getTotal();
- long refundAmount_wx = amount_wx.getRefund();
- Long playTotal_wx = amount_wx.getPayerTotal();
- refundTransaction.setTransactionId(transactionId_wx);
- refundTransaction.setPayAmount(playTotal_wx);
- refundTransaction.setTotalAmount(total_wx);
- refundTransaction.setOrderId(orderId_wx);
- refundTransaction.setRefundId(refundId_wx);
- transactionService.updateByBo(BeanCopyUtils.copy(refundTransaction, CourseTransactionBo.class));
- return R.ok("申请成功, 请注意查收退款记录");
- } catch (Exception e) {
- e.printStackTrace();
- throw e;
- }
- }
-
- public R getRefundsOrder(Long id) {
- try {
- // 具体业务自行处理 此处ID为商户系统流水ID
- QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
- request.setSubMchid(payConfig.getMerchantId());
- request.setOutRefundNo(transaction.getId().toString());
- Refund refundResp = refundService.queryByOutRefundNo(request);
-
- return R.fail();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- }
- import cn.hutool.core.date.DateUtil;
- import com.wechat.pay.java.service.billdownload.BillDownloadServiceExtension;
- import com.wechat.pay.java.service.billdownload.DigestBillEntity;
- import com.wechat.pay.java.service.billdownload.model.AccountType;
- import com.wechat.pay.java.service.billdownload.model.BillType;
- import com.wechat.pay.java.service.billdownload.model.GetFundFlowBillRequest;
- import com.wechat.pay.java.service.billdownload.model.GetTradeBillRequest;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.stereotype.Service;
-
- import javax.annotation.Resource;
- import javax.servlet.http.HttpServletResponse;
- import java.io.InputStream;
-
- /**
- * @author: wxj
- * @Desc: 微信支付下载服务类
- * @create: 2023-12-06 17:37:49
- **/
-
- @Slf4j
- @Service
- public class WechatBillDownloadService {
- @Resource
- private BillDownloadServiceExtension downloadService;
-
- /**
- * @param billDate 日期 不填默认昨天
- * @param billTypeStr 导出内容类型
- * ALL: 返回当日所有订单信息(不含充值退款订单)
- * SUCCESS: 返回当日成功支付的订单(不含充值退款订单)
- * REFUND: 返回当日退款订单(不含充值退款订单)
- * RECHARGE_REFUND: 返回当日充值退款订单
- * ALL_SPECIAL: 返回个性化账单当日所有订单信息
- * SUC_SPECIAL: 返回个性化账单当日成功支付的订单
- * REF_SPECIAL: 返回个性化账单当日退款订单
- * @param tarType 压缩类型 不填默认ZGIP
- * @return 流
- */
-
- public R<InputStream> exportTransactions(String billDate, String tarType, String billTypeStr, HttpServletResponse resp) {
- if (StringUtils.isEmpty(billDate)) {
- billDate = DateUtil.format(DateUtil.yesterday(), "yyyy-MM-DD");
- }
- BillType billType = BillType.ALL;
- try {
- billType = BillType.valueOf(billTypeStr);
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- }
- GetTradeBillRequest request = new GetTradeBillRequest();
- request.setBillDate(billDate);
- request.setBillType(billType);
- request.setTarType(null);
- DigestBillEntity tradeBill = downloadService.getTradeBill(request);
- return R.ok(tradeBill.getInputStream());
- }
-
-
- public R<InputStream> exportFundflow(String billDate, String accountTypeStr, HttpServletResponse resp) {
- if (StringUtils.isEmpty(billDate)) {
- billDate = DateUtil.format(DateUtil.yesterday(), "yyyy-MM-DD");
- }
- AccountType accountType = AccountType.ALL;
- try {
- accountType = AccountType.valueOf(accountTypeStr);
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- }
- GetFundFlowBillRequest request = new GetFundFlowBillRequest();
- request.setBillDate(billDate);
- request.setTarType(null);
- request.setAccountType(accountType);
- DigestBillEntity fundFlowBill = downloadService.getFundFlowBill(request);
- return R.ok(fundFlowBill.getInputStream());
- }
-
- }
安卓app的接口大差不差也都这样,不知道方法或者参数接收的兄弟可以看SDK源码,实在找不到idea不能搜索jar中的代码,建议反编译之后再用idea打开搜索,毕竟我就是这么做的...
这些接口暂时还没完整测试, 过段时间测通过上线了再把支付宝的也分享出来...
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。