?大家好,我是小悟
(資料圖片)
在對(duì)接支付寶開放平臺(tái)的一些常用功能時(shí),常常需要收到支付寶的回調(diào)通知結(jié)果,才能處理業(yè)務(wù)邏輯。此文介紹通過WebSocket長(zhǎng)連接接入支付寶消息服務(wù),實(shí)現(xiàn)消息通知。
包括五部分內(nèi)容:?jiǎn)栴}、優(yōu)勢(shì)、配置、代碼接入、總結(jié)。
比如接入互聯(lián)網(wǎng)平臺(tái)直付通二級(jí)商戶進(jìn)件時(shí),需要知道這個(gè)進(jìn)件審核的結(jié)果,是審核通過還是審核拒絕,就要用到直付通商戶進(jìn)件審核通過消息接口和直付通二級(jí)商戶進(jìn)件拒絕消息接口。
再比如接入支付寶小程序模板開發(fā)時(shí),需要知道第三應(yīng)用授權(quán)取消結(jié)果、小程序?qū)徍私Y(jié)果、服務(wù)商代創(chuàng)建小程序結(jié)果等等,就要用到第三方應(yīng)用授權(quán)取消消息接口、小程序?qū)徍送ㄟ^通知接口、小程序?qū)徍笋g回通知接口、商戶確認(rèn)服務(wù)商代創(chuàng)建小程序結(jié)果通知接口等等。
雖然可以通過對(duì)應(yīng)的查詢接口主動(dòng)發(fā)起查詢結(jié)果,但多個(gè)業(yè)務(wù)結(jié)果還需開發(fā)多個(gè)查詢接口,體驗(yàn)終歸不如由支付寶服務(wù)端側(cè)直接通知開發(fā)者來的好。所以千萬別干“脫褲子放pi,多此一舉”的事情來,哈哈哈。
為了解決通知的問題,支付寶開放平臺(tái)消息服務(wù)提供兩種通訊協(xié)議來接收消息,一種是基于 HTTPS/HTTP,一種是基于 WebSocket 長(zhǎng)連接。
選擇WebSocket 長(zhǎng)連接有諸多優(yōu)勢(shì):
官方提供封裝好的SDK,開發(fā)者無需考慮通信、驗(yàn)簽、組裝報(bào)文協(xié)議,只要專心根據(jù)收到的消息處理自身的業(yè)務(wù)邏輯即可。
無需申請(qǐng)https證書,減少繁瑣的證書申請(qǐng)工作,消息也能觸達(dá)。
開發(fā)者無需額外開發(fā)一個(gè)服務(wù)來接收開放平臺(tái)的消息。
相比之下,WebSocket 長(zhǎng)連接有更多的優(yōu)勢(shì),所以一般選擇使用WebSocket 長(zhǎng)連接來接收支付寶服務(wù)端發(fā)來的消息。
創(chuàng)建好應(yīng)用后,在產(chǎn)品綁定-綁定產(chǎn)品,添加對(duì)應(yīng)的產(chǎn)品。
然后在開發(fā)設(shè)置-消息服務(wù)-FROM平臺(tái)訂閱所需監(jiān)聽的消息接口,接入方式選擇WebSocket。
以上操作是接入的前提條件,務(wù)必檢查清楚再進(jìn)行代碼的開發(fā)。
可使用普通公鑰方式和公鑰證書方式接入,方式不同,SDK的使用也不同,這個(gè)取決于設(shè)置接口加簽是何種方式,這邊選擇的是公鑰證書方式。
在代碼中引入依賴,這邊有個(gè)注意點(diǎn)就是,如果選擇的是公鑰證書模式的話,SDK版本需要使用4.11.54.ALL 及以上版本。
com.alipay.sdk alipay-sdk-java 4.11.54.ALL
這個(gè)是重點(diǎn),開發(fā)一個(gè)支付寶消息配置類,支付寶服務(wù)端有消息通知時(shí)會(huì)自動(dòng)觸發(fā)。
@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() { /** * 客戶端接收到消息后回調(diào)此方法 * @param msgApi 接收到的消息的消息api名 * @param msgId 接收到的消息的消息id * @param bizContent 接收到的消息的內(nèi)容,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("用戶信息申請(qǐng)記錄審核通知,接收到的消息內(nèi)容:{}", bizContent); } else if (StringUtils.equals("alipay.open.auth.appauth.cancelled", msgApi)) { logger.info("第三方應(yīng)用授權(quán)取消消息,接收到的消息內(nèi)容:{}", bizContent); } else if (StringUtils.equals("alipay.open.auth.userauth.cancelled", msgApi)) { logger.info("用戶授權(quán)取消消息,接收到的消息內(nèi)容:{}", bizContent); } else if (StringUtils.equals("alipay.open.mini.version.audit.passed", msgApi)) { logger.info("小程序?qū)徍送ㄟ^通知,接收到的消息內(nèi)容:{}", bizContent); } else if (StringUtils.equals("alipay.open.mini.version.audit.rejected", msgApi)) { logger.info("小程序?qū)徍笋g回通知,接收到的消息內(nèi)容:{}", bizContent); } else if (StringUtils.equals("alipay.trade.refund.depositback.completed", msgApi)) { logger.info("收單退款沖退完成通知,接收到的消息內(nèi)容:{}", bizContent); } else if (StringUtils.equals("alipay.open.mini.merchant.confirmed", msgApi)) { logger.info("商戶確認(rèn)服務(wù)商代創(chuàng)建小程序結(jié)果通知,接收到的消息內(nèi)容:{}", bizContent); } } }); alipayMsgClient.connect(); return alipayMsgClient; }
上面代碼的AliPayProperties類是配置了應(yīng)用的一些參數(shù)信息,包括應(yīng)用id、加簽類型、應(yīng)用私鑰證書路徑、應(yīng)用公鑰證書路徑、支付寶公鑰證書路徑、支付寶根證書路徑、編碼格式。
@Data@ConfigurationProperties(prefix = "alipay")public class AliPayProperties { /** * 加簽類型 */ private String signType; /** * 應(yīng)用id */ private String appId; /** * 請(qǐng)求使用的編碼格式,如utf-8,gbk,gb2312等 */ private String chartSet; /** * 應(yīng)用私鑰證書路徑 */ private String appCertPrivateKeyPath; /** * 應(yīng)用公鑰證書路徑 */ private String appCertPublicKeyPath; /** * 支付寶公鑰證書路徑 */ private String aliPayCertPublicKeyPath; /** * 支付寶根證書路徑 */ private String aliPayRootCertPath;}
當(dāng)支付寶服務(wù)端有給客戶端發(fā)送消息時(shí),會(huì)回調(diào)MsgHandler里面onMessage的實(shí)現(xiàn),因此可以在onMessage中處理接收到的消息,根據(jù)msgApi消息名判斷是哪種接口來處理對(duì)應(yīng)的業(yè)務(wù)邏輯。
但需要注意的是,因各種異常原因,支付寶服務(wù)端可能會(huì)重復(fù)通知,因此為了業(yè)務(wù)不重復(fù)被處理,需要做冪等性的控制,可根據(jù)每條消息的唯一msgId或者自身系統(tǒng)的業(yè)務(wù)id比如uuid來事先查詢。
您的一鍵三連,是我更新的最大動(dòng)力,謝謝
山水有相逢,來日皆可期,謝謝閱讀,我們?cè)贂?huì)
我手中的金箍棒,上能通天,下能探海
上一篇:??一不小心,登上支付寶開發(fā)者社區(qū)熱文榜單Top3??