WebSocket长连接接入支付宝消息服务,实现消息通知

数据结
• 阅读 1137

大家好,我是小悟

在对接支付宝开放平台的一些常用功能时,常常需要收到支付宝的回调通知结果,才能处理业务逻辑。此文介绍通过WebSocket长连接接入支付宝消息服务,实现消息通知。

包括五部分内容:问题、优势、配置、代码接入、总结。

WebSocket长连接接入支付宝消息服务,实现消息通知

问题
比如接入互联网平台直付通二级商户进件时,需要知道这个进件审核的结果,是审核通过还是审核拒绝,就要用到直付通商户进件审核通过消息接口和直付通二级商户进件拒绝消息接口。

再比如接入支付宝小程序模板开发时,需要知道第三应用授权取消结果、小程序审核结果、服务商代创建小程序结果等等,就要用到第三方应用授权取消消息接口、小程序审核通过通知接口、小程序审核驳回通知接口、商户确认服务商代创建小程序结果通知接口等等。

虽然可以通过对应的查询接口主动发起查询结果,但多个业务结果还需开发多个查询接口,体验终归不如由支付宝服务端侧直接通知开发者来的好。所以千万别干“脱裤子放pi,多此一举”的事情来,哈哈哈。

WebSocket长连接接入支付宝消息服务,实现消息通知

为了解决通知的问题,支付宝开放平台消息服务提供两种通讯协议来接收消息,一种是基于 HTTPS/HTTP,一种是基于 WebSocket 长连接。

优势
选择WebSocket 长连接有诸多优势:

官方提供封装好的SDK,开发者无需考虑通信、验签、组装报文协议,只要专心根据收到的消息处理自身的业务逻辑即可。

无需申请https证书,减少繁琐的证书申请工作,消息也能触达。

开发者无需额外开发一个服务来接收开放平台的消息。

相比之下,WebSocket 长连接有更多的优势,所以一般选择使用WebSocket 长连接来接收支付宝服务端发来的消息。

配置
创建好应用后,在产品绑定-绑定产品,添加对应的产品。

WebSocket长连接接入支付宝消息服务,实现消息通知

然后在开发设置-消息服务-FROM平台订阅所需监听的消息接口,接入方式选择WebSocket。

WebSocket长连接接入支付宝消息服务,实现消息通知

WebSocket长连接接入支付宝消息服务,实现消息通知

接入
以上操作是接入的前提条件,务必检查清楚再进行代码的开发。

可使用普通公钥方式和公钥证书方式接入,方式不同,SDK的使用也不同,这个取决于设置接口加签是何种方式,这边选择的是公钥证书方式。

WebSocket长连接接入支付宝消息服务,实现消息通知

在代码中引入依赖,这边有个注意点就是,如果选择的是公钥证书模式的话,SDK版本需要使用4.11.54.ALL 及以上版本。

<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java -->
<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-sdk-java</artifactId>
    <version>4.11.54.ALL</version>
</dependency>

这个是重点,开发一个支付宝消息配置类,支付宝服务端有消息通知时会自动触发。

@Component
@Configuration
@EnableConfigurationProperties({AliPayProperties.class})
public class AliPayMsgConfig {
    private static Logger logger = LoggerFactory.getLogger(AliPayMsgConfig.class);
    private AliPayProperties aliPay;
    public AliPayMsgConfig(AliPayProperties aliPay) {
        this.aliPay = aliPay;
    }
    @Bean
    public AlipayMsgClient alipayMsgClient() throws Exception {
        AlipayMsgClient alipayMsgClient = AlipayMsgClient.getInstance(aliPay.getAppId());
        alipayMsgClient.setConnector("openchannel.alipay.com");
        alipayMsgClient.setSecurityCertConfig(aliPay.getSignType(), FileUtil.readUtf8String(aliPay.getAppCertPrivateKeyPath()), aliPay.getAppCertPublicKeyPath(), aliPay.getAliPayCertPublicKeyPath(), aliPay.getAliPayRootCertPath());
        alipayMsgClient.setCharset(aliPay.getChartSet());
        alipayMsgClient.setMessageHandler(new MsgHandler() {
            /**
             * 客户端接收到消息后回调此方法
             *  @param  msgApi 接收到的消息的消息api名
             *  @param  msgId 接收到的消息的消息id
             *  @param  bizContent 接收到的消息的内容,json格式
             */
            @Override
            public void onMessage (String msgApi, String msgId, String bizContent) {
                logger.info("receive message. msgApi:{},msgId:{},bizContent:{}", msgApi, msgId, bizContent);
                if (StringUtils.equals("alipay.open.app.api.field.changed", msgApi)) {
                    logger.info("用户信息申请记录审核通知,接收到的消息内容:{}", bizContent);
                } else if (StringUtils.equals("alipay.open.auth.appauth.cancelled", msgApi)) {
                    logger.info("第三方应用授权取消消息,接收到的消息内容:{}", bizContent);
                } else if (StringUtils.equals("alipay.open.auth.userauth.cancelled", msgApi)) {
                    logger.info("用户授权取消消息,接收到的消息内容:{}", bizContent);
                } else if (StringUtils.equals("alipay.open.mini.version.audit.passed", msgApi)) {
                    logger.info("小程序审核通过通知,接收到的消息内容:{}", bizContent);
                } else if (StringUtils.equals("alipay.open.mini.version.audit.rejected", msgApi)) {
                    logger.info("小程序审核驳回通知,接收到的消息内容:{}", bizContent);
                } else if (StringUtils.equals("alipay.trade.refund.depositback.completed", msgApi)) {
                    logger.info("收单退款冲退完成通知,接收到的消息内容:{}", bizContent);
                } else if (StringUtils.equals("alipay.open.mini.merchant.confirmed", msgApi)) {
                    logger.info("商户确认服务商代创建小程序结果通知,接收到的消息内容:{}", bizContent);
                }
            }
        });
        alipayMsgClient.connect();
        return alipayMsgClient;
    }
}

别嫌if else长,这是demo,怎么方便怎么来。上面代码的AliPayProperties类是配置了应用的一些参数信息,包括应用id、加签类型、应用私钥证书路径、应用公钥证书路径、支付宝公钥证书路径、支付宝根证书路径、编码格式。

@Data
@ConfigurationProperties(prefix = "alipay")
public class AliPayProperties {
    /**
     * 加签类型
     */
    private String signType;
    /**
     * 应用id
     */
    private String appId;
    /**
     * 请求使用的编码格式,如utf-8,gbk,gb2312等
     */
    private String chartSet;
    /**
     * 应用私钥证书路径
     */
    private String appCertPrivateKeyPath;
    /**
     * 应用公钥证书路径
     */
    private String appCertPublicKeyPath;
    /**
     * 支付宝公钥证书路径
     */
    private String aliPayCertPublicKeyPath;
    /**
     * 支付宝根证书路径
     */
    private String aliPayRootCertPath;
}

总结
当支付宝服务端有给客户端发送消息时,会回调MsgHandler里面onMessage的实现,因此可以在onMessage中处理接收到的消息,根据msgApi消息名判断是哪种接口来处理对应的业务逻辑。

但需要注意的是,因各种异常原因,支付宝服务端可能会重复通知,因此为了业务不重复被处理,需要做幂等性的控制,可根据每条消息的唯一msgId或者自身系统的业务id比如uuid来事先查询。

WebSocket长连接接入支付宝消息服务,实现消息通知

您的一键三连,是我更新的最大动力,谢谢

山水有相逢,来日皆可期,谢谢阅读,我们再会

我手中的金箍棒,上能通天,下能探海

上一篇:一不小心,登上支付宝开发者社区热文榜单Top3

点赞
收藏
评论区
推荐文章
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
MaxSky MaxSky
4年前
PHP 接入支付宝公钥证书指南
为了简单快速的接入,在申请支付宝商户后,我们可通过沙箱应用进行测试准备证书首先登录支付宝开放平台沙箱环境:在RSA2(SHA256)密钥设置中的加签模式选择公钥证书,然后访问下载对应操作系统的支付宝开放平台开发助手打开支付宝开放平台开发助手后,直接点击左下角获取CSR文件:【你没看错,就
不是海碗 不是海碗
2年前
语音通知短信 API:一种新型的信息传递方式
实现语音通知短信的功能,我们需要借助语音通知短信的API接口,语音通知短信API是一种将文字转换为语音并通过电话呼叫或发送语音消息的API。
Wesley13 Wesley13
4年前
java程序支付宝接口付费功能的实现
以前做过c应用程序支付宝api接口功能,现在转移到Java程序上,代码如何实现呢?1、从你的网站提交到支付宝:/\\\将订单提交支付宝进行网上支付\/publicActionForwardsubmitAlipayUrl(ActionMappingmapping,ActionFormform,HttpServletReque
Stella981 Stella981
4年前
Netty干货分享:京东京麦的生产级TCP网关技术实践总结
1、引言京东的京麦商家后台2014年构建网关,从HTTP网关发展到TCP网关。在2016年重构完成基于Netty4.xProtobuf3.x实现对接PC和App上下行通信的高可用、高性能、高稳定的TCP长连接网关。早期京麦搭建HTTP和TCP长连接功能主要用于消息通知的推送,并未应用于API网关。随着逐步对NIO的深入学习和对Netty框
Wesley13 Wesley13
4年前
@PostConstruct注解,你该好好看看
在最近的工作中,get到一个很实用的注解,分享给诸位。痛点做过微信或支付宝支付的童鞋,可能遇到过这种问题,就是填写支付结果回调,就是在支付成功之后,支付宝要根据我们给的地址给我们进行通知,通知我们用户是否支付成功,如果成功我们就要去处理下面相应的业务逻辑,如果在测试服务,那么这个回调地址我们就需要填写测试服务的,如果发布到线上那么我们就需要改成
Stella981 Stella981
4年前
Android 必备进阶之百度推送
写在前边今天给大家推送一篇关于百度推送的文章。我们手机上常用的App都会时不时的推送消息在我们的消息栏显示,常用的是QQ消息推送、微信消息推送、支付宝转账消息推送等。以后再做大大小小的项目都会用到推送,今天就总结了一篇用百度云做推送消息,以后做项目会经常用到的,有时间就学习一下吧!!(https://oscimg.oschin
Stella981 Stella981
4年前
Linux应急响应(二):捕捉短连接
0x00前言​短连接(shortconnnection)是相对于长连接而言的概念,指的是在数据传送过程中,只在需要发送数据时,才去建立一个连接,数据发送完成后,则断开此连接,即每次连接只完成一项业务的发送。在系统维护中,一般很难去察觉,需要借助网络安全设备或者抓包分析,才能够去发现。0x01应急场景​
Stella981 Stella981
4年前
RabbitMQ延迟消息发送
为什么使用延迟消息?不同于同步消息,有些业务场景下希望可以实现延迟一定时间再消费消息。典型的场景有微信、支付宝等第三方支付回调接口,会在用户支付后3秒、5秒、30秒等等时间后向应用服务器发送回调请求,确保应用服务器可以正确收到消息。那有些朋友就会说了,把需要定时处理的数据存到数据库中用定时任务就可以实现,为什么还弄个异步消息。增加后台维护
Stella981 Stella981
4年前
Notification使用详解之三:通过服务更新进度通知&在Activity中监听服务进度
上次我们讲到如何实现一个可更新的进度通知,实现的方式是启动一个线程模拟一个下载任务,然后根据任务进度向UI线程消息队列发送进度消息,UI线程根据进度消息更新通知的UI界面。可是在实际应用中,我们一般会将上传、下载等比较耗时的后台任务以服务的形式运行,更新进度通知也是交由后台服务来完成的。不过有的时候,除了在通知里面显示进度信息,我们也要在Activit
程序员小五 程序员小五
1年前
融云IM干货丨如果用户不在线,推送通知会怎样处理?
如果用户不在线,融云的推送通知会按照以下方式处理:离线消息推送:当用户不在线时,融云会将收到的单聊消息、群聊消息、系统消息、超级群消息通过第三方推送厂商或融云自建的推送服务通知客户端。这意味着即使用户的应用没有运行,他们也能通过系统通知栏接收到消息提醒。服
数据结
数据结
Lv1
孤帆远影碧空尽,唯见长江天际流。
文章
10
粉丝
0
获赞
0