Skip to main content

PaymentRequiredException

Namespace: RA.Utilities.Core.Exceptions

PaymentRequiredException signals that the requested resource requires payment before it can be accessed. The API layer maps it to HTTP 402 Payment Required.

🎯 Purpose​

Use this exception for paywalls and billing gates: a subscription that has not been purchased, an exhausted prepaid balance, or a quota that only a paid plan unlocks. The meaning is "I know who you are, but this resource is not included in your current plan."

Do not use it for missing or invalid credentials (UnauthorizedException, 401), for a caller who is not allowed at all (ForbiddenException, 403), or for rate limiting (TooManyRequestsException, 429). A 402 tells the client that the request can succeed after payment.

Constructors​

ConstructorErrorCodeMessage
PaymentRequiredException()402BaseResponseMessages.PaymentRequired ("Payment is required to access this resource.")
PaymentRequiredException(string message)402supplied
PaymentRequiredException(int errorCode, string? message = null)suppliedsupplied, or BaseResponseMessages.PaymentRequired when null/omitted

The type always sets ResponseType.PaymentRequired. The two-argument constructor is the only one that changes ErrorCode.

Properties​

PropertyTypeDescription
ErrorCodeintInherited. 402 unless supplied explicitly.
ResponseTypeResponseTypeInherited. ResponseType.PaymentRequired.
MessagestringInherited. See the constructor table.

🚀 How to Use​

using RA.Utilities.Core.Results;
using RA.Utilities.Core.Exceptions;

public async Task<Result<Report>> GenerateReportAsync(Guid userId)
{
Subscription subscription = await _subscriptions.GetAsync(userId);

if (subscription.Plan == Plan.Free)
{
return new PaymentRequiredException("This report is available on paid plans.");
}

return await _reports.GenerateAsync(userId);
}

To attach a domain code while keeping the default message, pass null:

throw new PaymentRequiredException(errorCode: 4020);

🔗 HTTP mapping​

ErrorResultResponse recognizes PaymentRequiredException and returns HTTP 402 with a PaymentRequiredResponse. The envelope carries responseCode from ErrorCode, responseType as PaymentRequired, and responseMessage from Message; there is no nested result payload:

{
"responseCode": 402,
"responseType": 18,
"responseMessage": "Payment is required to access this resource.",
"result": null
}

With JsonStringEnumConverter, responseType is "PaymentRequired". Because the mapper selects the status from the exception type, overriding ErrorCode does not change the 402 status.

See ErrorResultResponse for how exception types are mapped to results.