在支付网关的业务中,在用户支付成功/失败后需要异步通知业务方,这个时候业务方是一个变数,支付网关可以定义一个interface,各个业务方来实现这个接口。

支付网关配置一个回调配置表,表中包含:group、ZK的注册地址等dubbo调用必须要的参数值。

dubbo在ZK上的注册信息示例:

dubbo://192.168.18.234:20883/com.wy.payment.service.CutPaymentService?anyhost=true&application=installment&default.timeout=30000&dubbo=2.5.3&interface=com.wy.payment.service.CutPaymentService&methods=updateRepaymentPlan,updatePaymentOrderStatus,selectOrderByCondition,createRepaymentPlan,selectPayWaterByBid,cutPayment&pid=31913&revision=0.0.1-SNAPSHOT&side=provider&timestamp=1489374649211

动手开干,先建配置表。

 CREATE TABLE `pay_callback_config` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`system_id` varchar(20) DEFAULT NULL COMMENT '业务系统标识',
`registry_address` varchar(100) DEFAULT NULL COMMENT 'zk注册地址',
`registry_group` varchar(50) DEFAULT NULL COMMENT 'zk注册组',
`registry_version` varchar(20) DEFAULT NULL COMMENT '服务的版本号',
`valid_flag` tinyint(1) DEFAULT '' COMMENT '是否有效,1有效 0无效',
`create_date` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='支付回调的配置表';

对应的domain类:

 package xxx.domain;

 import java.io.Serializable;
import java.util.Date; import xxx.PaymentConstants; import lombok.Data; /**
* 支付回调的相关配置 对应表:pay_callback_config
*
* @author yangzhilong
*
*/
@Data
public class PayCallbackConfig implements Serializable{
/**
*
*/
private static final long serialVersionUID = 339298526553679045L; private Long id;
/**
* 业务系统标识 {@link PaymentConstants.BUSINESS_SYSTEM}
*/
private String systemId;
/**
* zk注册地址
*/
private String registryAddress;
/**
* zk注册组
*/
private String registryGroup;
/**
* 服务的版本号
*/
private String registryVersion;
/**
* 有效标识
*/
private Boolean validFlag;
/**
* 创建时间
*/
private Date createDate;
}

Spring Boot的配置类:

 package xx.configuration;

 import java.util.List;

 import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import xx.domain.PayCallbackConfig;
import xx.mapper.PayCallbackConfigMapper;
import xx.utils.PayCallbackUtils;
import xx.utils.UselessBean; /**
* 支付回调的初始化代码
*
* @author yangzhilong
*
*/
@Configuration
@ConditionalOnClass(PayCallbackConfigMapper.class)
public class PayCallbackConfiguration {
@Autowired
private PayCallbackConfigMapper payCallbackConfigMapper; @Bean
UselessBean uselessBean(){
List<PayCallbackConfig> list = payCallbackConfigMapper.listAllVaild();
if(null != list && !list.isEmpty()){
for(PayCallbackConfig item : list){
PayCallbackUtils.init(item.getSystemId(), item.getRegistryAddress(), item.getRegistryGroup(), item.getRegistryVersion());
}
}
UselessBean uselessBean = new UselessBean();
return uselessBean;
} }

其中UselessBean就是一个空的类,定义这个就是利用spring对该类的初始来帮我初始化PayCallbackUtils类。

package xx.utils;

/**
* 不会用的一个bean,只是用来在@Configuration帮忙初始化PayCallbackUtils的数据
*
* @author yangzhilong
*
*/
public class UselessBean { }

真正的核心类:PayCallbackUtils

 package xx.utils;

 import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import xx.api.payment.HuaPayCallbackService;
import xx.dto.payment.HuapayCallbackDTO; public class PayCallbackUtils {
// 当前应用的信息
private static ApplicationConfig application = new ApplicationConfig();
// 注册中心信息缓存
private static Map<String, RegistryConfig> registryConfigCache = new ConcurrentHashMap<>();
// 各个业务方的ReferenceConfig缓存
private static Map<String, ReferenceConfig<HuaPayCallbackService>> referenceCache = new ConcurrentHashMap<>(); static {
application.setName("test");
} /**
* 获取注册中心信息
*
* @param address
* zk注册地址
* @param group
* dubbo服务所在的组
* @return
*/
private static RegistryConfig getRegistryConfig(String address, String group, String version) {
String key = address + "-" + group + "-" + version;
RegistryConfig registryConfig = registryConfigCache.get(key);
if (null == registryConfig) {
registryConfig = new RegistryConfig();
registryConfig.setAddress(address);
registryConfig.setGroup(group); registryConfigCache.put(key, registryConfig);
}
return registryConfig;
} /**
* 获取服务的代理对象
*
* @param business
* @param address
* @param group
* @return
*/
private static ReferenceConfig<HuaPayCallbackService> getReferenceConfig(String business, String address,
String group, String version) {
String referenceKey = business;
ReferenceConfig<HuaPayCallbackService> referenceConfig = referenceCache.get(referenceKey);
if (null == referenceConfig) {
referenceConfig = new ReferenceConfig<>();
referenceConfig.setApplication(application);
referenceConfig.setRegistry(getRegistryConfig(address, group, version));
referenceConfig.setInterface(HuaPayCallbackService.class);
referenceConfig.setVersion(version); referenceCache.put(referenceKey, referenceConfig);
}
return referenceConfig;
} /**
* 初始化数据
*
* @param business
* @param address
* @param group
* @param version
*/
public static void init(String business, String address, String group, String version) {
getReferenceConfig(business, address, group, version);
} /**
* 调用远程服务
*
* @param business
* @param address
* @param group
* @param version
* @return
*/
public static boolean invoke(String business, PayCallbackDTO dto) {
ReferenceConfig<PayCallbackService> reference = getReferenceConfig(business, null, null, null);
if (null != reference) {
PayCallbackService callbackService = reference.get();
if (null != callbackService) {
return callbackService.callback(dto);
}
}
return false;
}
}

其中HuaPayCallbackService是我定义的支付回调的接口定义,业务系统的回调服务必须实现我这个接口。

示例代码如下:

 package xx.api.payment;

 import xx.dto.payment.PayCallbackDTO;

 /**
* 支付异步回调统一的接口
*
* @author yangzhilong
*
*/
public interface PayCallbackService {
/**
* 回调的接口
*
* @param callbackDTO
* @return 成功我就不会再回调,失败我会有重试的机制
*/
boolean callback(HuapayCallbackDTO callbackDTO);
}

回调参数的DTO:

package xx.gateway.dto.payment;

import java.io.Serializable;

import lombok.Data;
import lombok.EqualsAndHashCode; @Data
@EqualsAndHashCode(callSuper = false)
public class PayCallbackDTO implements Serializable {
/**
*
*/
private static final long serialVersionUID = -3475086707314113975L;
/**
* 支付状态 {@link xx.PaymentConstants.PAY_STATUS}
*/
private String payStatus;
/**
* 支付失败的原因
*/
private String payErrorInfo;
/**
* 业务系统订单id
*/
private String businessOrderId;
/**
* 支付流水id
*/
private String payFlowId;
/**
* 支付渠道返回的code
*/
private String channelRetCode;
/**
* 金额,单位:元
*/
private String money;
}

本文参考DUBBO官方文档实现:http://dubbo.io/API+Config-zh.htm

最新文章

  1. 6_Win7下Chrome主页被流氓网站hao123.com劫持后的解决方法。
  2. Linux shell循环
  3. DOM 之 SAX操作
  4. Java类的初始化过程及清理
  5. 小技巧--让JS代码只执行一次
  6. Linux进程间通信IPC学习笔记之消息队列(SVR4)
  7. CSS3秘笈复习:第九章&amp;第十章
  8. LeetCode OJ 86. Partition List
  9. vuejs学习笔记(1)--属性,事件绑定,ajax
  10. (5)ES6解构赋值-函数篇
  11. 自动删除文件脚本(Linux shell脚本)
  12. mysql的order by注入
  13. Spring之BeanFactory和FactoryBean接口的区别
  14. Quartz+TopShelf实现定时任务
  15. Swoole PHP windows composer
  16. KVM虚拟化图
  17. 阿里大于发送短信(java)
  18. metrics 开发监控实现jdbc
  19. DPDK helloworld 源码阅读
  20. Vue-router浅识

热门文章

  1. java 常用集合list与Set、Map区别及适用场景总结
  2. QT中使用MinGW 编译的protobuf库--包含库的生成和使用
  3. [leetcode]Regular Expression Matching @ Python
  4. VS2010整合NUnit进行单元测试
  5. iOS开发-UIButton浅谈
  6. 【图片识别】Java中使用tess4J进行图片文字识别(支持中文)(转)
  7. Kafka:ZK+Kafka+Spark Streaming集群环境搭建(六)针对spark2.2.1以yarn方式启动spark-shell抛出异常:ERROR cluster.YarnSchedulerBackend$YarnSchedulerEndpoint: Sending RequestExecutors(0,0,Map(),Set()) to AM was unsuccessful
  8. [Spring Boot] Use Component Scan to scan for Bean
  9. redis-dev
  10. redis 中 set 和 hset 有什么不同,什么时候使用 hset 什么时候使用set?