微信支付宝支付实现 (基于Elegent-pay框架)与接口幂等性 - 2025/7/29

首先你需要有个商户号, 劝退...

微信和支付宝支付的流程大致相同

image

用户支付成功后

image

支付框架 : https://gitee.com/myelegent/elegent-pay

官网介绍

ElegentPay是封装了支付宝和微信支付的支付框架,用户使用该框架,可以用最小的学习成本,在几分钟内快速集成并在项目中使用。

  • 为支付宝和微信提供了统一的调用入口。
  • 支持native、小程序、H5、APP等多种支付方式,并提供统一入口。
  • 提供了统一的dto类作为前端的调用参数,用户使用简便。
  • 封装了回调入口和验签逻辑,简化了用户编写支付回调中繁琐的验签逻辑。
  • 提供了扩展机制,用户可以自定义其它的支付方式。
  • 对支付回调和退款回调提供了幂等性校验。
  • 提供了回调补偿功能。

准备工作

1.在项目中引入依赖:(按需引入)

<!--微信支付-->
<dependency>
    <groupId>cn.elegent.pay</groupId>
    <artifactId>elegent-pay-wxpay</artifactId>
    <version>1.0.0</version>
</dependency>
<!--支付宝支付-->
<dependency>
    <groupId>cn.elegent.pay</groupId>
    <artifactId>elegent-pay-alipay</artifactId>
    <version>1.0.0</version>
</dependency>

2.在项目配置文件添加配置:(按需配置)

elegent:
  pay:
    wxpay:
      mchId: 1561414331
      appId: wx6592a2db3f85ed25
      appSecret: d9a9ff00a633cd7353a8925119063b01
      mchSerialNo: 25FBDE3EFD31B03A4377EB9A4A47C517969E6620
      apiV3Key: CZBK51236435wxpay435434323FFDuv3
    alipay:
      appId: 2021003141676135
    callback:
      domain: https://2d3ac179.r5.cpolar.top
      watch: true
      cycle: 10

wxpay(微信支付)配置说明

(1)mchId: 商户号

(2)appId: APP编号

(3)appSecret: app密钥

(4)mchSerialNo : 商户证书序列号

(5)apiV3Key : v3版本密钥

alipay(支付宝)配置说明

(1)appId:APP编号

callback(回调通知)配置说明

(1)domain:工程域名根目录。如果在本地调试,建议使用内网穿透工具生成此地址。

(2)watch:是否开启回调监察。如果开启,将根据用户给出的本地未支付订单记录进行支付状态查询,如果已支付则自动进行回调处理。缺省值为false。

(3)cycle: 回调监察周期,单位为秒。缺省值为10。

3.添加微信私钥和支付宝公钥、私钥

在resources目录下创建wxpay_private.key,用户存储微信私钥

在resources目录下创建alipay_private.key,用户存储支付宝私钥

在resources目录下创建alipay_public.key,用户存储支付宝公钥

Controller层代码

@Autowired
private ElegentPay elegentPay;


@PostMapping("/requestPay/{tradeType}/{platform}")
    public PayResponse requestPay(@RequestBody PayDto payDto, @PathVariable("tradeType") String tradeType, @PathVariable("platform") String platform) {
        log.info("请求支付{}" , payDto);
        // 创建订单
        Order order = orderService.createOrder(payDto, platform);
        // 创建支付请求
        PayRequest payRequest = new PayRequest();
        // 设置订单编号
        payRequest.setBody(order.getSkuName());
        // 设置订单金额
        payRequest.setTotalFee(order.getAmount());
        // 设置订单号
        payRequest.setOrderSn(order.getOrderNo());
        payRequest.setOpenid(order.getOpenId());
        return elegentPay.requestPay(payRequest, tradeType, platform);
    }

支付回调代码

@Service
@Slf4j
public class CallBackServiceImpl implements CallBackService {

    @Autowired
    private OrderService orderService;


    @Override
    public void successPay(String orderSn) {
        Order order = orderService.getOrderByNo(orderSn);
        if(order != null) {

            if (order.getStatus().equals(OrderStatus.ORDER_STATUS_CREATE)) {
                order.setStatus(OrderStatus.ORDER_STATUS_PAYED); //订单状态  已支付
                order.setPayStatus(PayStatus.PAY_STATUS_PAYED);//支付状态  成功
                orderService.updateById(order);
                //todo 发货
            }
            // todo 发货代码
        }
    }

    @Override
    public void failPay(String orderSn) {
        log.info("支付失败回调!"+orderSn);
    }

    @Override
    public void successRefund(String orderSn) {
        log.info("退款成功回调!"+orderSn);
        Order order = orderService.getOrderByNo(orderSn);
        if (order != null) {
            order.setPayStatus(PayStatus.PAY_STATUS_REFUNDIED);// 支付状态:退款成功
            orderService.updateById(order);
        }
    }

    @Override
    public void failRefund(String orderSn) {
        log.info("退款失败回调!"+orderSn);
        Order order = orderService.getOrderByNo(orderSn);
        if (order != null) {
            order.setPayStatus(PayStatus.PAY_STATUS_REFUNDING);// 支付状态:退款中
            orderService.updateById(order);
        }
    }

}

接口幂等性

接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。

举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条,这就没有保证接口的幂等性。

解决方案

  • 令牌机制实现

image

  • 序列号机制实现

通过sn机制实现接口的幂等性,示意图如下:

image

这是一个基于springboot的优雅的幂等性框架。使用这个组件可以让你更轻松、更优雅地在项目中实现接口幂等性处理,让你更专注业务代码的开发。它目前支持令牌和序列号两种检查策略。用户只需要在方法上添加一个注解,即可实现接口幂等性。

使用方法

将代码拉到本地 , install到本地仓库进行使用

详细步骤
image

使用

1)在pom.xml添加依赖

<!--幂等性框架-->
<dependency>
    <groupId>cn.elegent.idem</groupId>
    <artifactId>elegent-idem-core</artifactId>
    <version>1.1.0</version>
</dependency>

(2)在application.yml中添加配置

elegent:
  pay:
    wxpay:
      mchId: 1561414331
      appId: wxffb3637a228223b8
      appSecret: 84311df9199ecacdf4f12d27b6b9522d
      mchSerialNo: 4B3B3DC35414AD50B1B755BAF8DE9CC7CF407606
      apiV3Key: CZBK51236435wxpay435434323FFDuv3
    alipay:
      appId: 2021003141676135
    callback:
      domain: http://20dfc451.r8.cpolar.top
      watch: true
      cycle: 10
  idem:
    redis:
      host: 192.168.200.128
      port: 6379
      password:

(3)在OrderController的requestPay方法上添加注解

@ElegentIdem(type="sn" ,name="requestId")
@PostMapping("/requestPay/{tradeType}/{platform}")
public PayResponse requestPay(@RequestBody PayDto payDto, @PathVariable("tradeType") String tradeType, @PathVariable("platform") String platform) {
    //1. 创建订单
    Order order = orderService.createOrder(payDto, platform);//创建订单
    //2. 调用支付
    PayRequest param=new PayRequest();
    param.setBody(order.getSkuName());//商品名称
    param.setOrderSn(order.getOrderNo());//订单编号
    param.setTotalFee(order.getAmount().intValue());//订单金额
    param.setOpenid(order.getOpenId());//openid
    return elegentPay.requestPay(param, tradeType, platform);
}
posted @ 2025-08-04 21:08  XYu1230  阅读(118)  评论(0)    收藏  举报