添加sender
1 去playground 走通业务 。
playground 地址。
developer.flash-fx.com/senders api.dev.flash-fx.com.au
1.1 login 拿token .
```
mutation ($loginInput: LoginInput!) {
login(input: $loginInput) {
token
message
code
success
}
}
//variables
{
"loginInput": {
"email": "devops@latipay.net",
"password": "Latipay2022"
}
}
```
得到响应的数据
```json
{
"data": {
"login": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2MGQ1NTkzMDU3MmMxYzUyYjhjZThmYzQiLCJjbGllbnRJZCI6IjYwZDU1OTMwNTcyYzFjMDcxZWNlOGZjNyIsImlhdCI6MTY2MTgzMzg2MiwiZXhwIjoxNjYxOTIwMjYyfQ.hXlPy8WymLdRDJCj4924oFjehf9VXteJqEVwBY_pyoU",
"message": "OK",
"code": "SUCCESS",
"success": true
}
}
}
```
1.2 在playground 走通createSender
先参考手册
实现一个简版的走通。
mutation ($SenderInput: SenderInput!) {
createSender(input: $SenderInput) {
success
code
message
sender {
id
nickName,
}
}
}
//设置header 通过1.1 login 获取
{"authorization":"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2MGQ1NTkzMDU3MmMxYzUyYjhjZThmYzQiLCJjbGllbnRJZCI6IjYwZDU1OTMwNTcyYzFjMDcxZWNlOGZjNyIsImlhdCI6MTY2MTgzMzg2MiwiZXhwIjoxNjYxOTIwMjYyfQ.hXlPy8WymLdRDJCj4924oFjehf9VXteJqEVwBY_pyoU"}
//设置请求变量
{
"SenderInput": {
"firstName": "xu",
"lastName": "xing",
"email":"13823761206@163.com",
"address": {
"street": "1 Test st",
"suburb": "London",
"state": "TST",
"country": "GB",
"postcode": "2000"
}
}
}
走通后响应如下。
{
"data": {
"createSender": {
"success": true,
"code": "CREATED",
"message": "New sender created",
"sender": {
"id": "630dadd0a0b12a29510286fc",
"nickName": "xuxing"
}
}
}
}
让响应内容丰富一些。
mutation ($SenderInput: SenderInput!) {
createSender(input: $SenderInput) {
success
code
message
sender {
id
nickName,
}
}
}
调整后,效果如图。
2 开发service
2.1 定义请求体结构。 (习惯就好,json 带子结构,就用子类来包一下)
namespace FlashFxPayment.Shared.Services.FlashFx.Models.Sender
{
public class SenderInput
{
public string FirstName { get; set; } = default!;
public string LastName { get; set; } = default!;
public string Email { get; set; } = default!;
public SenderAddress Address { get; set; } = default!;
}
public class SenderAddress
{
public string? Street { get; set; } = default;
public string? Suburb { get; set; } = default;
public string? State { get; set; } = default;
public CountryIso2? Country { get; set; } = default;
public string? Postcode { get; set; } = default;
}
}
2.2 定义响应
override tostring 方便打日志的时候看数据。
namespace FlashFxPayment.Shared.Services.FlashFx.Models.Sender
{
public class CreateSenderReply
{
public bool Success { get; set; }
public string Code { get; set; } = default!;
public string Message { get; set; } = default!;
public Sender Sender { get; set; } = default!;
public override string ToString()
{
return "CreateSenderRelay: Success:" + Success + " Code:" + Code+ " Message:" + Message + " <SenderResponse> Sender" + Sender.ToString() + " base:" +base.ToString();
}
}
public class Sender
{
//id 好像是
public string Id { get; set; } = default!;
//昵称
public string NickName { get; set; } = default!;
public string Email { get; set; } = default!;
public override string ToString()
{
return "Id:"+Id + " - NickName" + NickName + " - Email:" + Email + " | base: " + base.ToString();
}
}
}
再用 Response包一下。
public class CreateSenderResponse
{
public CreateSenderReply CreateSender { get; set; }
}
2.3 实现业务方法
//创建Sender
public async Task<CreateSenderReply?> CreateSender(string? token, String firstName, String lastName, String email, SenderAddress address)
{
try
{
var createSenderRequest = new GraphQLRequest
{
Query = @"mutation ($senderInput: SenderInput!) {
createSender(input: $senderInput) {
success
message
code
sender {
id
nickName
email
}
}}
",
Variables = new
{
senderInput = new SenderInput
{
FirstName = firstName ,
LastName = lastName,
Email = email,
Address = address
}
}
};
_client.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var result = await _client.SendQueryAsync<CreateSenderResponse>(createSenderRequest);
if ((result.Errors == null || result.Errors?.Length == 0) && result.Data.CreateSender != null)
{
_logger.LogInformation("--------------------- Code SendQueryAsyncResponse ------" + result.Data.CreateSender?.Code);
_logger.LogInformation("--------------------- Message SendQueryAsyncResponse ------" + result.Data.CreateSender?.Message);
_logger.LogInformation("--------------------- Success SendQueryAsyncResponse ------" + result.Data.CreateSender?.Success);
_logger.LogInformation("--------------------- Sender.Id CreateSender _client.SendQueryAsync ------" + result.Data.CreateSender?.Sender?.Id);
_logger.LogInformation("--------------------- Sender.NickName CreateSender _client.SendQueryAsync ------" + result.Data.CreateSender?.Sender?.NickName);
_logger.LogInformation("--------------------- Sender.obj CreateSender _client.SendQueryAsync ------" + result.Data.CreateSender?.Sender);
var myReturn = result.Data.CreateSender;
_logger.LogInformation("||------------" + myReturn.ToString());
return result.Data.CreateSender;
} else {
_logger.LogInformation("error");
return null;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "FlashFxService.CreateSender: Failed to create sender");
return null;
}
}
3 开发api (将用户请求,转为grapthQl 业务请求。)
请求结构。
预计一个用户请求为
{
"firstName":"xu",
"lastName":"xing",
"email":"13823761206@163.com",
"address":{
"street":"test333",
"state":"London",
"suburb":"urb test1",
"country":"GB",
"postcode":"2000"
}
}
//定义请求结构。
public class CreateSenderRequest
{
public string? FirstName;
public string? LastName;
public string? Email;
// public CreateSenderAddressRequest? Address;
public AddressRequest? Address;
}
public class CreateSenderAddressRequest
{
public string? Street { get; set; }
public string? State { get; set; }
public string? Suburb { get; set; }
public CountryIso2? Country { get; set; }
public string? Postcode { get; set; }
}
响应结构
public class CreateSenderResponse
{
public string Id { get; set; } = default!;
public string NickName { get; set; } = default!;
public string Email { get; set; } = default!;
public override string ToString()
{
return "CreateSenderResponse: Id:" + Id+ " - Nickname:" + NickName +" - Email:" + Email + " - " + base.ToString();
}
}
实现控制器代码。
[Route("api/sender/create-sender")]
[TokenAuthorize]
public async Task<IActionResult> CreateSender([FromBody] CreateSenderRequest request)
{
try
{
//HttpContext.GetToken();
_logger.LogInformation("Token = {Token}", HttpContext.GetToken());
//一些输入校验。
if (string.IsNullOrWhiteSpace(request.FirstName))
{
return BadRequest(BaseResponse.Create(ResponseCode.ApiParameterIsMissing, nameof(request.FirstName).Lower(true)));
}
if (string.IsNullOrWhiteSpace(request.LastName))
{
return BadRequest(BaseResponse.Create(ResponseCode.ApiParameterIsMissing, nameof(request.LastName).Lower(true)));
}
_logger.LogInformation("here to send reqest");
/*
if (request.Address == null)
{
return BadRequest(BaseResponse.Create(ResponseCode.ApiParameterIsMissing, nameof(request.Address).Lower(true)));
}
*/
_logger.LogInformation("------- controller start to send --------------" + request.FirstName + " - " + request.LastName);
var address = request.Address.Adapt<SenderAddress>();
//先走通不带address
var senderRelay = await _flashFxService.CreateSender(HttpContext.GetToken(), request.FirstName, request.LastName, request.Email, address);
// _logger.LogInformation("_flashFxService:CreateSender" + senderRelay.ToString());
if (senderRelay == null)
{
return BadRequest(BaseResponse.Create(ResponseCode.ApiSenderCreateFailed));
} else {
var MyData = senderRelay.Adapt<Models.Sender.CreateSenderResponse>();
_logger.LogInformation("||||------- controller response --------------" + senderRelay.ToString() );
}
return Ok(new DataResponse<Models.Sender.CreateSenderResponse>
{
Data = senderRelay.Adapt<Models.Sender.CreateSenderResponse>()
});
}
catch (Exception ex)
{
_logger.LogError(ex, "AuthController.Login: Failed to log in");
return InternalError(BaseResponse.Create(ResponseCode.Failure));
}
}
注意参数和响应的转换。
//注意dto 要转换。
// 1 请求时,要将request 中的 address 转为 service 中的 SenderAddress 对象。
//结构完全一致时。
var address = request.Address.Adapt<SenderAddress>();
// 2 返回时,要将 senderReply 转为 senderReply.Adapt<Models.Sender.CreateSenderResponse>()
//由于 CreateSenderRelay 和 SenderResponse 结构不一致 所以需要写map .
TypeAdapterConfig<CreateSenderReply, CreateSenderResponse>
.ForType()
.Map(dest => dest.Id, src => src.Sender.Id)
.Map(dest => dest.NickName, src => src.Sender.NickName)
.Map(dest => dest.Email, src => src.Sender.Email);