tech.carpentum.sdk.payment.PaymentContext.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payment-client-v2 Show documentation
Show all versions of payment-client-v2 Show documentation
Carpentum Payment system Java SDK
package tech.carpentum.sdk.payment
import tech.carpentum.sdk.payment.PaymentContext.Builder
import tech.carpentum.sdk.payment.internal.api.EnhancedAuthApi
import tech.carpentum.sdk.payment.internal.api.PostAuthTokensErrorExceptionFactory
import tech.carpentum.sdk.payment.internal.api.ResponseExceptionUtils
import tech.carpentum.sdk.payment.model.AuthTokenRequest
import tech.carpentum.sdk.payment.model.AuthTokenResponse
import tech.carpentum.sdk.payment.model.Money
import tech.carpentum.sdk.payment.model.PostAuthTokensError
import java.io.InterruptedIOException
import java.time.Duration
import java.util.*
import java.util.function.Supplier
/**
* The **root API class** used by any other individual APIs to call Payment RESTful API.
* The class is thread safe. It is expected the context class is singleton in custom application.
* Use [Builder] to create new instance of the class.
*
* The `PaymentContext` holds references and default values to call Payment RESTful API.
* There are available overloaded methods `createAuthToken` to create new instance of Authorization token.
* The context instance is as well used with individual API classes:
*
* - [AccountsApi]
* - [IncomingPaymentsApi]
* - [OutgoingPaymentsApi]
* - [PaymentsApi]
* - [MerchantInfoApi]
*/
class PaymentContext private constructor(
val apiBaseUrl: String,
val apiVersion: Int,
val merchantCode: String,
val brand: String?,
val secret: String,
/**
* Default validity of Authorization token.
* Used by [createAuthToken] method in case `tokenValidity` parameter is not specified.
*/
val defaultTokenValidity: Duration,
/**
* Default request call timeout.
*/
val defaultCallTimeout: Duration
) {
private val authApi: EnhancedAuthApi = EnhancedAuthApi(apiBaseUrl, defaultCallTimeout)
private fun validityInSeconds(tokenValidity: Duration?): Int =
(tokenValidity ?: defaultTokenValidity).seconds.toInt()
/**
* Throws [PostAuthTokensErrorException] ("406" response) with one of defined
* [PostAuthTokensError] business validation error code.
* Throws [InterruptedIOException] in case of timeout.
*/
@JvmOverloads
@Throws(ResponseException::class, InterruptedIOException::class)
// tag::userGuidePublicApi[]
fun createAuthToken(
operations: List,
tokenValidity: Duration? = null,
money: Optional = Optional.empty()
): AuthTokenResponse
// end::userGuidePublicApi[]
{
val validityInSeconds = validityInSeconds(tokenValidity)
val requestBodyBuilder = AuthTokenRequest.builder()
.merchantCode(merchantCode)
.secret(secret)
.validitySecs(validityInSeconds)
.operations(operations)
money.ifPresent { moneyRequest -> requestBodyBuilder.money(moneyRequest) }
val requestBody = requestBodyBuilder.build()
return ResponseExceptionUtils.wrap(PostAuthTokensErrorExceptionFactory.instance) {
authApi.createAuthToken(xAPIVersion = apiVersion, authTokenRequest = requestBody)
}
}
/**
* Throws [PostAuthTokensErrorException] ("406" response) with one of defined
* [PostAuthTokensError] business validation error code.
* Throws [InterruptedIOException] in case of timeout.
*/
@JvmOverloads
@Throws(ResponseException::class, InterruptedIOException::class)
// tag::userGuidePublicApi[]
fun createAuthToken(
operationsSupplier: Supplier>,
tokenValidity: Duration? = null,
money: Optional = Optional.empty()
): AuthTokenResponse
// end::userGuidePublicApi[]
{
return createAuthToken(operationsSupplier.get(), tokenValidity, money)
}
/**
* Factory to create a new instance of [Builder] to build new instance of [PaymentContext].
*/
companion object Factory {
/**
* Environment variable name for specifying default value for [Builder.domain] property.
* One of [ENV_TECH_CARPENTUM_SDK_PAYMENT_API_BASE_URL] property or this property is mandatory.
* Specified [ENV_TECH_CARPENTUM_SDK_PAYMENT_API_BASE_URL] property overrides [ENV_TECH_CARPENTUM_SDK_PAYMENT_DOMAIN] property.
*
* @see ENV_TECH_CARPENTUM_SDK_PAYMENT_API_BASE_URL
*/
const val ENV_TECH_CARPENTUM_SDK_PAYMENT_DOMAIN = "TECH_CARPENTUM_SDK_PAYMENT_DOMAIN"
/**
* Environment variable name for specifying default value for [Builder.apiBaseUrl] property.
* One of [ENV_TECH_CARPENTUM_SDK_PAYMENT_DOMAIN] property or this property is mandatory.
* Specified [ENV_TECH_CARPENTUM_SDK_PAYMENT_API_BASE_URL] property overrides [ENV_TECH_CARPENTUM_SDK_PAYMENT_DOMAIN] property.
*
* @see ENV_TECH_CARPENTUM_SDK_PAYMENT_DOMAIN
*/
const val ENV_TECH_CARPENTUM_SDK_PAYMENT_API_BASE_URL = "TECH_CARPENTUM_SDK_PAYMENT_API_BASE_URL"
/**
* Environment variable name for specifying default value for [Builder.merchantCode] property.
*/
const val ENV_TECH_CARPENTUM_SDK_PAYMENT_MERCHANT_CODE = "TECH_CARPENTUM_SDK_PAYMENT_MERCHANT_CODE"
/**
* Environment variable name for specifying default value for [Builder.secret] property.
*/
const val ENV_TECH_CARPENTUM_SDK_PAYMENT_SECRET = "TECH_CARPENTUM_SDK_PAYMENT_SECRET"
/**
* Environment variable name for specifying default value for [Builder.defaultCallTimeout] property.
* The value is a number in seconds.
*/
const val ENV_TECH_CARPENTUM_SDK_PAYMENT_CALL_TIMEOUT = "TECH_CARPENTUM_SDK_PAYMENT_CALL_TIMEOUT"
private const val apiVersion: Int = 2
private const val apiBaseUrlPrefix: String = "https://api."
private val defaultTokenValidity: Duration = Duration.ofMinutes(1)
private val defaultCallTimeout: Duration = Duration.ofSeconds(30)
@JvmStatic
fun builder(): Builder = Builder()
}
/**
* Builder to create a new instance of [PaymentContext].
*
* Mandatory properties to be set:
*
* - [domain]
* - [merchantCode]
* - [secret]
*/
class Builder {
private var apiBaseUrl: String? =
Optional.ofNullable(System.getenv(ENV_TECH_CARPENTUM_SDK_PAYMENT_API_BASE_URL))
.orElseGet {
Optional.ofNullable(System.getenv(ENV_TECH_CARPENTUM_SDK_PAYMENT_DOMAIN))
.map(::formatApiBaseUrl)
.orElse(null)
}
private var merchantCode: String? = System.getenv(ENV_TECH_CARPENTUM_SDK_PAYMENT_MERCHANT_CODE)
private var brand: String? = null
private var secret: String? = System.getenv(ENV_TECH_CARPENTUM_SDK_PAYMENT_SECRET)
private var defaultTokenValidity: Duration = Factory.defaultTokenValidity
private var defaultCallTimeout: Duration =
Optional.ofNullable(System.getenv(ENV_TECH_CARPENTUM_SDK_PAYMENT_CALL_TIMEOUT))
.map {
try {
it.toLong()
} catch (ex: NumberFormatException) {
throw IllegalArgumentException("Environment variable $ENV_TECH_CARPENTUM_SDK_PAYMENT_CALL_TIMEOUT wrong number format: $it")
}
}
.map { Duration.ofSeconds(it) }
.orElseGet { Factory.defaultCallTimeout }
private fun formatApiBaseUrl(domain: String): String = apiBaseUrlPrefix + domain
/**
* Payment RESTful API domain, e.g. `carpentum.tech`.
* Default value can be specified via [ENV_TECH_CARPENTUM_SDK_PAYMENT_DOMAIN] environment variable.
*
* @see [apiBaseUrl]
*/
fun domain(domain: String) = apply { this.apiBaseUrl = formatApiBaseUrl(domain) }
/**
* Payment RESTful API domain, e.g. `carpentum.tech`.
* Default value can be specified via [ENV_TECH_CARPENTUM_SDK_PAYMENT_API_BASE_URL] environment variable.
*
* @see [domain]
*/
fun apiBaseUrl(apiBaseUrl: String) = apply { this.apiBaseUrl = apiBaseUrl }
/**
* Unique merchant code obtained during the merchant registration process.
* Default value can be specified via [ENV_TECH_CARPENTUM_SDK_PAYMENT_MERCHANT_CODE] environment variable.
*/
fun merchantCode(merchantCode: String) = apply { this.merchantCode = merchantCode }
/**
* Current payment system brand code.
*/
fun brand(brand: String) = apply { this.brand = brand }
/**
* Merchant secret obtained upon merchant registration process.
* Default value can be specified via [ENV_TECH_CARPENTUM_SDK_PAYMENT_SECRET] environment variable.
*/
fun secret(secret: String) = apply { this.secret = secret }
/**
* Default auth token validity if not specified on every [PaymentContext.createAuthToken] call.
* If not specified, `1 minute` by default.
*/
fun defaultTokenValidity(tokenValidity: Duration) = apply { this.defaultTokenValidity = tokenValidity }
/**
* Default request call timeout if not specified while creating API instances.
* Default value can be specified via [ENV_TECH_CARPENTUM_SDK_PAYMENT_CALL_TIMEOUT] environment variable.
* If not specified, `30 seconds` by default.
*
* @see AccountsApi.Factory.create
* @see IncomingPaymentsApi.Factory.create
* @see OutgoingPaymentsApi.Factory.create
* @see PaymentsApi.Factory.create
* @see MerchantInfoApi.Factory.create
*/
fun defaultCallTimeout(callTimeout: Duration) = apply { this.defaultCallTimeout = callTimeout }
/**
* Create new instance of [PaymentContext].
*/
fun build(): PaymentContext = PaymentContext(
apiBaseUrl = requireNotNull(apiBaseUrl) { "One of 'domain' or 'apiBaseUrl' properties is mandatory." },
apiVersion = apiVersion,
merchantCode = requireNotNull(merchantCode) { "Property 'merchantCode' is mandatory." },
brand = brand,
secret = requireNotNull(secret) { "Property 'secret' is mandatory." },
defaultTokenValidity = defaultTokenValidity,
defaultCallTimeout = defaultCallTimeout,
)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy