0
点赞
收藏
分享

微信扫一扫

Biz-SIP中间件之xbank项目实战(5)——支付域服务的开发


xbank项目版本库:​​https://gitee.com/szhengye/xbank.git​​

项目实践:支付域服务的开发

1. Payment领域服务的封装

payment领域服务是对接第三方缴费平台的,第三方缴费平台的接口是XML报文格式。

payment领域服务是属于对接第三方的领域服务,前面提到的customer领域服务和account领域服务,主要是内部交易处理的领域服务。

这二类领域服务在开发时有比较大的不同:


  • 对接第三方的领域服务,一般涉及到复杂的通讯接口对接和报文格式转换;
  • 内部交易处理领域服务,应用层和领域层之间,建议采用约定的Interface接口类的调用约定(底层Biz-SIP平台自动转换成RESTful协议和BizMessage标准消息进行交互)。

在开发对接第三方的领域服务时,建议采用实现SinkBeanInterface接口的JavaBean或SpringBean:

public interface SinkBeanInterface {
/**
* Java服务调用接口
* @param beforeJsonObject 打包前的JsonObject
* @param packMessage 传入的消息
* @return 返回值
* @throws BizException
*/
public byte[] process(JSONObject beforeJsonObject, byte[] packMessage) throws BizException;
}

在process()方法中传入的beforeJsonObject参数,是传入sink但还没经过打包的JSONObject对象,packMessage参数已经根据sink的消息格式配置,完成了对于目标消息格式的转换。


Payment领域服务的封装,依次有以下步骤:


第1步


领域服务的实现:创建xbank-payment1-sink子模块,根据SinkBeanInterface接口,实现Payment1SinkService微服务,并封装成能独立运行的微服务应用:

@Service
public class Payment1SinkService implements SinkBeanInterface {
@Override
public byte[] process(JSONObject beforeJsonObject, byte[] inMessage) throws BizException {
log.info("传入消息:\n{}", BizUtils.buildHexLog(inMessage));
return inMessage;
}
}


第2步


在sink.yml文件中,把Payment1SinkService微服务作为Sink连接到Biz-SIP平台:

- id: payment1-sink
type: rest
url: http://payment1-sink/sink
converter:
type: simple-xml
connector:
type: sink-bean
class-name: com.xbank.sink.payment.service.Payment1SinkService
spring-bean: true

2. Payment服务的快速发布

配置service.yml文件,把payment-sink直接作为sink-service暴露给Biz-SIP开放平台接口:

- bizServiceId: sink/payment1
type: sink-service
sinkId: payment1-sink

接口测试如下:

$ curl -H "Content-Type:application/json" -H "Biz-Service-Id:sink/payment1" -X POST --data '{"message":"Hello world!"}' http://localhost:8888/api|jq

{
"code": 0,
"message": "success",
"extMessage": null,
"traceId": "af37bbbb495744d79f2f1811178436f5",
"parentTraceId": null,
"timestamp": 1631153112943,
"data": {
"message": "Hello world!"
}
}

Payment1SinkApplication会打印出日志,收到了完成消息转换后的XML报文:

2021-09-09 10:05:13.265  INFO 10756 --- [nio-8003-exec-1] c.x.d.p.service.Payment1DomainService    : 传入消息:
====+ 01-02-03-04-05-06-07-08-09-10-11-12-13-14-15-16-17-18-19-20 + ====== ASCII ====== +
0000: 3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 22 31 2E 30 22 20 | <?xml version="1.0" |
0020: 65 6E 63 6F 64 69 6E 67 3D 22 55 54 46 2D 38 22 20 73 74 61 | encoding="UTF-8" sta |
0040: 6E 64 61 6C 6F 6E 65 3D 22 6E 6F 22 3F 3E 3C 72 6F 6F 74 3E | ndalone="no"?><root> |
0060: 3C 6D 65 73 73 61 67 65 3E 48 65 6C 6C 6F 20 77 6F 72 6C 64 | <message>Hello world |
0080: 21 3C 2F 6D 65 73 73 61 67 65 3E 3C 2F 72 6F 6F 74 3E | !</message></root>.. |

3. payment领域服务在应用层和适配层的定制

通过在service.yml中配置sink-service聚合服务,能实现已经挂接到Sink的领域服务的快速发布。

但是,客户针对应用层和适配层,还是有个性化定制要求,这就涉及到应用层和适配层的定制。

例如我们要实现一个把消息发送给缴费平台的业务,输入的消息包括:交易码、传递的消息。

首先,需要在xbank-personal-app-client子模块中的PersonalAppInterface接口,增加一个消息发送接口send2payment1(),这个接口是共享给应用层和适配层的:

public interface PersonalAppInterface {
...
public BizMessage send2Payment1(Object message) throws BizException;
...
}

然后在xbank-app模块中基于此接口方法。在PersonalAppService类实现接口:

public class PersonalAppService implements PersonalAppInterface {
...
private BizMessageInterface payment1DomainInterface = IntegratorClientFactory
.getSinkClient(BizMessageInterface.class,"payment1-sink");
...
@Override
public BizMessage<JSONObject> send2Payment1(Object message) throws BizException {
JSONObject jsonObject = new JSONObject();
jsonObject.set("message",message);
return this.payment1DomainInterface.call(jsonObject);
}
...
}

由于payment领域服务没有另外约定接口,是采用BizMessage标准消息接口,所以是采用BizMessageInterface接口来构建sink调用接口的,并统一通过call()方法来调用领域服务。

由于前面已经在service.yml中把PersonalAppService应用层服务类,配置成了“bean-service”的聚合服务,所以可以直接进行接口调用:

$ curl -H "Content-Type:application/json" -H "Biz-Service-Id:app/personal" -X POST --data '{"methodName":"send2Payment1","params":["Hello world!"]}' http://localhost:8888/api|jq

{
"code": 0,
"message": "success",
"extMessage": null,
"traceId": "19620fe5843d4d53a2bf1f599b516006",
"parentTraceId": null,
"timestamp": 1631153624870,
"data": {
"result": {
"traceId": "19620fe5843d4d53a2bf1f599b516006",
"code": 0,
"data": {
"message": "Hello world!"
},
"message": "success",
"timestamp": 1631153624870
}
}
}

Payment1SinkApplication应用会收到消息:

2021-09-09 10:13:44.911  INFO 10756 --- [nio-8003-exec-2] c.x.d.p.service.Payment1DomainService    : 传入消息:
====+ 01-02-03-04-05-06-07-08-09-10-11-12-13-14-15-16-17-18-19-20 + ====== ASCII ====== +
0000: 3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 22 31 2E 30 22 20 | <?xml version="1.0" |
0020: 65 6E 63 6F 64 69 6E 67 3D 22 55 54 46 2D 38 22 20 73 74 61 | encoding="UTF-8" sta |
0040: 6E 64 61 6C 6F 6E 65 3D 22 6E 6F 22 3F 3E 3C 72 6F 6F 74 3E | ndalone="no"?><root> |
0060: 3C 6D 65 73 73 61 67 65 3E 48 65 6C 6C 6F 20 77 6F 72 6C 64 | <message>Hello world |
0080: 21 3C 2F 6D 65 73 73 61 67 65 3E 3C 2F 72 6F 6F 74 3E | !</message></root>.. |

在适配层中,在原有的PersonalController类中,增加对“/send2Payment1"请求的实现:

@GetMapping(value ="/send2Payment1")
public BizMessage<JSONObject> send2Payment1(String message) throws BizException {
return this.personalAppInterface.send2Payment1(message);
}

开发者可以在适配层的PersonalController类中,通过personalAppInterface,把消息发送给缴费平台:

$ curl http://localhost:9001/personal/send2Payment1\?message=hello|jq 

{
"code": 0,
"message": "success",
"extMessage": null,
"traceId": "3c9d800b3c76480c9ae605d543709ea3",
"parentTraceId": null,
"timestamp": 1631154087879,
"data": {
"message": "hello"
}
}

在适配层中,还可以通过配置sink-service类型的聚合服务,直接调用领域层的Sink服务。例如可以在原有的PersonalController类中,直接向应用层发起JSONObject类型的平台报文:

@RestController
@RequestMapping("/personal")
public class PersonalController {
...
private BizMessageInterface payment1SinkInterface = SourceClientFactory
.getBizServiceClient(BizMessageInterface.class,"sink/payment1");
...
@GetMapping(value ="/send2Payment")
public BizMessage<JSONObject> send2Payment(String message) throws BizException {
JSONObject jsonObject = new JSONObject();
jsonObject.set("message",message);
return this.payment1SinkInterface.call(jsonObject);
}
}

开发者可以在适配层的PersonalController类中,通过personalAppInterface,把消息发送给缴费平台:

$ curl http://localhost:9001/personal/send2Payment1\?message=hello|jq 

{
"code": 0,
"message": "success",
"extMessage": null,
"traceId": "3c9d800b3c76480c9ae605d543709ea3",
"parentTraceId": null,
"timestamp": 1631154087879,
"data": {
"message": "hello"
}
}

Biz-SIP官方网站:​​​http://bizsip.bizmda.com​​​

Gitee:​​​https://gitee.com/szhengye/biz-sip​​​



举报

相关推荐

0 条评论