idempotency key delivery fix
This commit is contained in:
@@ -69,7 +69,10 @@ func (h *quotePaymentCommand) Execute(
|
|||||||
return h.mapQuoteErr(err)
|
return h.mapQuoteErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return gsresponse.Success(&orchestratorv1.QuotePaymentResponse{Quote: quoteProto})
|
return gsresponse.Success(&orchestratorv1.QuotePaymentResponse{
|
||||||
|
IdempotencyKey: req.GetIdempotencyKey(),
|
||||||
|
Quote: quoteProto,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *quotePaymentCommand) prepareQuoteCtx(req *orchestratorv1.QuotePaymentRequest) (*quoteCtx, error) {
|
func (h *quotePaymentCommand) prepareQuoteCtx(req *orchestratorv1.QuotePaymentRequest) (*quoteCtx, error) {
|
||||||
@@ -315,9 +318,10 @@ func (h *quotePaymentsCommand) Execute(
|
|||||||
)
|
)
|
||||||
|
|
||||||
return gsresponse.Success(&orchestratorv1.QuotePaymentsResponse{
|
return gsresponse.Success(&orchestratorv1.QuotePaymentsResponse{
|
||||||
QuoteRef: quoteRef,
|
IdempotencyKey: req.GetIdempotencyKey(),
|
||||||
Aggregate: aggregate,
|
QuoteRef: quoteRef,
|
||||||
Quotes: quotes,
|
Aggregate: aggregate,
|
||||||
|
Quotes: quotes,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -248,6 +248,7 @@ message QuotePaymentsResponse {
|
|||||||
string quote_ref = 1;
|
string quote_ref = 1;
|
||||||
PaymentQuoteAggregate aggregate = 2;
|
PaymentQuoteAggregate aggregate = 2;
|
||||||
repeated PaymentQuote quotes = 3;
|
repeated PaymentQuote quotes = 3;
|
||||||
|
string idempotency_key = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message InitiatePaymentsRequest {
|
message InitiatePaymentsRequest {
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ type FxQuote struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PaymentQuote struct {
|
type PaymentQuote struct {
|
||||||
IdempotencyKey string `json:"idempotencyKey"`
|
|
||||||
QuoteRef string `json:"quoteRef,omitempty"`
|
QuoteRef string `json:"quoteRef,omitempty"`
|
||||||
DebitAmount *model.Money `json:"debitAmount,omitempty"`
|
DebitAmount *model.Money `json:"debitAmount,omitempty"`
|
||||||
ExpectedSettlementAmount *model.Money `json:"expectedSettlementAmount,omitempty"`
|
ExpectedSettlementAmount *model.Money `json:"expectedSettlementAmount,omitempty"`
|
||||||
@@ -67,8 +66,9 @@ type Payment struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type paymentQuoteResponse struct {
|
type paymentQuoteResponse struct {
|
||||||
authResponse `json:",inline"`
|
authResponse `json:",inline"`
|
||||||
Quote *PaymentQuote `json:"quote"`
|
IdempotencyKey string `json:"idempotencyKey,omitempty"`
|
||||||
|
Quote *PaymentQuote `json:"quote"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type paymentQuotesResponse struct {
|
type paymentQuotesResponse struct {
|
||||||
@@ -88,10 +88,11 @@ type paymentResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PaymentQuote wraps a payment quote with refreshed access token.
|
// PaymentQuote wraps a payment quote with refreshed access token.
|
||||||
func PaymentQuoteResponse(logger mlogger.Logger, quote *orchestratorv1.PaymentQuote, token *TokenData) http.HandlerFunc {
|
func PaymentQuoteResponse(logger mlogger.Logger, idempotencyKey string, quote *orchestratorv1.PaymentQuote, token *TokenData) http.HandlerFunc {
|
||||||
return response.Ok(logger, paymentQuoteResponse{
|
return response.Ok(logger, paymentQuoteResponse{
|
||||||
Quote: toPaymentQuote(quote),
|
Quote: toPaymentQuote(quote),
|
||||||
authResponse: authResponse{AccessToken: *token},
|
IdempotencyKey: idempotencyKey,
|
||||||
|
authResponse: authResponse{AccessToken: *token},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,9 +217,10 @@ func toPaymentQuotes(resp *orchestratorv1.QuotePaymentsResponse) *PaymentQuotes
|
|||||||
quotes = nil
|
quotes = nil
|
||||||
}
|
}
|
||||||
return &PaymentQuotes{
|
return &PaymentQuotes{
|
||||||
QuoteRef: resp.GetQuoteRef(),
|
IdempotencyKey: resp.GetIdempotencyKey(),
|
||||||
Aggregate: toPaymentQuoteAggregate(resp.GetAggregate()),
|
QuoteRef: resp.GetQuoteRef(),
|
||||||
Quotes: quotes,
|
Aggregate: toPaymentQuoteAggregate(resp.GetAggregate()),
|
||||||
|
Quotes: quotes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ func (a *PaymentAPI) quotePayment(r *http.Request, account *model.Account, token
|
|||||||
return response.Auto(a.logger, a.Name(), err)
|
return response.Auto(a.logger, a.Name(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sresponse.PaymentQuoteResponse(a.logger, resp.GetQuote(), token)
|
return sresponse.PaymentQuoteResponse(a.logger, resp.GetIdempotencyKey(), resp.GetQuote(), token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *PaymentAPI) quotePayments(r *http.Request, account *model.Account, token *sresponse.TokenData) http.HandlerFunc {
|
func (a *PaymentAPI) quotePayments(r *http.Request, account *model.Account, token *sresponse.TokenData) http.HandlerFunc {
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ part 'quotation.g.dart';
|
|||||||
class PaymentQuoteResponse extends BaseAuthorizedResponse {
|
class PaymentQuoteResponse extends BaseAuthorizedResponse {
|
||||||
|
|
||||||
final PaymentQuoteDTO quote;
|
final PaymentQuoteDTO quote;
|
||||||
|
final String idempotencyKey;
|
||||||
|
|
||||||
const PaymentQuoteResponse({required super.accessToken, required this.quote});
|
const PaymentQuoteResponse({required super.accessToken, required this.idempotencyKey, required this.quote});
|
||||||
|
|
||||||
factory PaymentQuoteResponse.fromJson(Map<String, dynamic> json) => _$PaymentQuoteResponseFromJson(json);
|
factory PaymentQuoteResponse.fromJson(Map<String, dynamic> json) => _$PaymentQuoteResponseFromJson(json);
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ part 'quotes.g.dart';
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class PaymentQuotesDTO {
|
class PaymentQuotesDTO {
|
||||||
final String quoteRef;
|
final String quoteRef;
|
||||||
|
final String idempotencyKey;
|
||||||
final PaymentQuoteAggregateDTO? aggregate;
|
final PaymentQuoteAggregateDTO? aggregate;
|
||||||
final List<PaymentQuoteDTO>? quotes;
|
final List<PaymentQuoteDTO>? quotes;
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@ class PaymentQuotesDTO {
|
|||||||
required this.quoteRef,
|
required this.quoteRef,
|
||||||
this.aggregate,
|
this.aggregate,
|
||||||
this.quotes,
|
this.quotes,
|
||||||
|
required this.idempotencyKey,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory PaymentQuotesDTO.fromJson(Map<String, dynamic> json) => _$PaymentQuotesDTOFromJson(json);
|
factory PaymentQuotesDTO.fromJson(Map<String, dynamic> json) => _$PaymentQuotesDTOFromJson(json);
|
||||||
|
|||||||
@@ -9,11 +9,13 @@ extension PaymentQuotesDTOMapper on PaymentQuotesDTO {
|
|||||||
quoteRef: quoteRef,
|
quoteRef: quoteRef,
|
||||||
aggregate: aggregate?.toDomain(),
|
aggregate: aggregate?.toDomain(),
|
||||||
quotes: quotes?.map((quote) => quote.toDomain()).toList(),
|
quotes: quotes?.map((quote) => quote.toDomain()).toList(),
|
||||||
|
idempotencyKey: idempotencyKey
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
extension PaymentQuotesMapper on PaymentQuotes {
|
extension PaymentQuotesMapper on PaymentQuotes {
|
||||||
PaymentQuotesDTO toDTO() => PaymentQuotesDTO(
|
PaymentQuotesDTO toDTO() => PaymentQuotesDTO(
|
||||||
|
idempotencyKey: idempotencyKey,
|
||||||
quoteRef: quoteRef,
|
quoteRef: quoteRef,
|
||||||
aggregate: aggregate?.toDTO(),
|
aggregate: aggregate?.toDTO(),
|
||||||
quotes: quotes?.map((quote) => quote.toDTO()).toList(),
|
quotes: quotes?.map((quote) => quote.toDTO()).toList(),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:pshared/api/responses/payment/quotation.dart';
|
||||||
import 'package:pshared/models/payment/fees/line.dart';
|
import 'package:pshared/models/payment/fees/line.dart';
|
||||||
import 'package:pshared/models/payment/fx/quote.dart';
|
import 'package:pshared/models/payment/fx/quote.dart';
|
||||||
import 'package:pshared/models/payment/money.dart';
|
import 'package:pshared/models/payment/money.dart';
|
||||||
@@ -23,3 +24,29 @@ class PaymentQuote {
|
|||||||
required this.fxQuote,
|
required this.fxQuote,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PaymentQuoteX extends PaymentQuote {
|
||||||
|
final String idempotencyKey;
|
||||||
|
|
||||||
|
const PaymentQuoteX({
|
||||||
|
required super.quoteRef,
|
||||||
|
required super.debitAmount,
|
||||||
|
required super.expectedSettlementAmount,
|
||||||
|
required super.expectedFeeTotal,
|
||||||
|
required super.feeLines,
|
||||||
|
required super.networkFee,
|
||||||
|
required super.fxQuote,
|
||||||
|
required this.idempotencyKey,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory PaymentQuoteX.build({required PaymentQuote quote, required String idempotencyKey}) => PaymentQuoteX(
|
||||||
|
quoteRef: quote.quoteRef,
|
||||||
|
debitAmount: quote.debitAmount,
|
||||||
|
expectedSettlementAmount: quote.expectedSettlementAmount,
|
||||||
|
expectedFeeTotal: quote.expectedFeeTotal,
|
||||||
|
feeLines: quote.feeLines,
|
||||||
|
networkFee: quote.networkFee,
|
||||||
|
fxQuote: quote.fxQuote,
|
||||||
|
idempotencyKey: idempotencyKey,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'package:pshared/models/payment/quote_aggregate.dart';
|
|||||||
|
|
||||||
class PaymentQuotes {
|
class PaymentQuotes {
|
||||||
final String quoteRef;
|
final String quoteRef;
|
||||||
|
final String idempotencyKey;
|
||||||
final PaymentQuoteAggregate? aggregate;
|
final PaymentQuoteAggregate? aggregate;
|
||||||
final List<PaymentQuote>? quotes;
|
final List<PaymentQuote>? quotes;
|
||||||
|
|
||||||
@@ -11,5 +12,6 @@ class PaymentQuotes {
|
|||||||
required this.quoteRef,
|
required this.quoteRef,
|
||||||
required this.aggregate,
|
required this.aggregate,
|
||||||
required this.quotes,
|
required this.quotes,
|
||||||
|
required this.idempotencyKey,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,10 +28,11 @@ import 'package:pshared/provider/recipient/pmethods.dart';
|
|||||||
import 'package:pshared/provider/resource.dart';
|
import 'package:pshared/provider/resource.dart';
|
||||||
import 'package:pshared/service/payment/quotation.dart';
|
import 'package:pshared/service/payment/quotation.dart';
|
||||||
import 'package:pshared/utils/currency.dart';
|
import 'package:pshared/utils/currency.dart';
|
||||||
|
import 'package:pshared/utils/exception.dart';
|
||||||
|
|
||||||
|
|
||||||
class QuotationProvider extends ChangeNotifier {
|
class QuotationProvider extends ChangeNotifier {
|
||||||
Resource<PaymentQuote> _quotation = Resource(data: null, isLoading: false, error: null);
|
Resource<PaymentQuoteX> _quotation = Resource(data: null, isLoading: false, error: null);
|
||||||
late OrganizationsProvider _organizations;
|
late OrganizationsProvider _organizations;
|
||||||
bool _isLoaded = false;
|
bool _isLoaded = false;
|
||||||
|
|
||||||
@@ -162,7 +163,7 @@ class QuotationProvider extends ChangeNotifier {
|
|||||||
return recipientName?.isNotEmpty == true ? recipientName : null;
|
return recipientName?.isNotEmpty == true ? recipientName : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setResource(Resource<PaymentQuote> quotation) {
|
void _setResource(Resource<PaymentQuoteX> quotation) {
|
||||||
_quotation = quotation;
|
_quotation = quotation;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
@@ -181,11 +182,7 @@ class QuotationProvider extends ChangeNotifier {
|
|||||||
_isLoaded = true;
|
_isLoaded = true;
|
||||||
_setResource(_quotation.copyWith(data: response, isLoading: false, error: null));
|
_setResource(_quotation.copyWith(data: response, isLoading: false, error: null));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_setResource(_quotation.copyWith(
|
_setResource(_quotation.copyWith(data: null, error: toException(e), isLoading: false));
|
||||||
data: null,
|
|
||||||
error: e is Exception ? e : Exception(e.toString()),
|
|
||||||
isLoading: false,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return _quotation.data;
|
return _quotation.data;
|
||||||
|
|||||||
@@ -16,14 +16,15 @@ class QuotationService {
|
|||||||
static final _logger = Logger('service.payment.quotation');
|
static final _logger = Logger('service.payment.quotation');
|
||||||
static const String _objectType = Services.payments;
|
static const String _objectType = Services.payments;
|
||||||
|
|
||||||
static Future<PaymentQuote> getQuotation(String organizationRef, QuotePaymentRequest request) async {
|
static Future<PaymentQuoteX> getQuotation(String organizationRef, QuotePaymentRequest request) async {
|
||||||
_logger.fine('Quoting payment for organization $organizationRef');
|
_logger.fine('Quoting payment for organization $organizationRef');
|
||||||
final response = await AuthorizationService.getPOSTResponse(
|
final response = await AuthorizationService.getPOSTResponse(
|
||||||
_objectType,
|
_objectType,
|
||||||
'/quote/$organizationRef',
|
'/quote/$organizationRef',
|
||||||
request.toJson(),
|
request.toJson(),
|
||||||
);
|
);
|
||||||
return PaymentQuoteResponse.fromJson(response).quote.toDomain();
|
final resp = PaymentQuoteResponse.fromJson(response);
|
||||||
|
return PaymentQuoteX.build(quote: resp.quote.toDomain(), idempotencyKey: resp.idempotencyKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<PaymentQuotes> getMultiQuotation(String organizationRef, QuotePaymentsRequest request) async {
|
static Future<PaymentQuotes> getMultiQuotation(String organizationRef, QuotePaymentsRequest request) async {
|
||||||
|
|||||||
Reference in New Issue
Block a user