Skip to content

Commit c957b7f

Browse files
committed
feat: Add Pricing API
1 parent fabd16a commit c957b7f

File tree

5 files changed

+242
-1
lines changed

5 files changed

+242
-1
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

7+
## [1.1.0] - 2024-11-??
8+
9+
### Added
10+
- Custom template management for Verify API
11+
- Pricing API
12+
713
## [1.0.0] - 2024-10-25
814
First stable GA release
915

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright 2024 Vonage
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.vonage.client.kt
17+
18+
import com.vonage.client.account.*
19+
20+
/**
21+
* Implementation of the [Pricing API](https://developer.vonage.com/en/api/pricing).
22+
*
23+
* *Authentication method:* API Key & secret.
24+
*
25+
* @since 1.1.0
26+
*/
27+
class Pricing internal constructor(private val client: AccountClient) {
28+
29+
/**
30+
* Retrieve the cost for sending an SMS to all supported countries.
31+
*
32+
* @return The list of pricing and network information for each country.
33+
*/
34+
fun listOutboundSmsPrices(): List<PricingResponse> =
35+
client.listPriceAllCountries(ServiceType.SMS)
36+
37+
/**
38+
* Retrieve the cost for making a voice call to all supported countries.
39+
*
40+
* @return The list of pricing and network information for each country.
41+
*/
42+
fun listOutboundVoicePrices(): List<PricingResponse> =
43+
client.listPriceAllCountries(ServiceType.VOICE)
44+
45+
/**
46+
* Retrieve the cost for sending an SMS to a given country code.
47+
*
48+
* @param countryCode The two-character country code.
49+
*
50+
* @return A [PricingResponse] object with the pricing and network information.
51+
*/
52+
fun getOutboundSmsPrice(countryCode: String): PricingResponse =
53+
client.getSmsPrice(countryCode)
54+
55+
/**
56+
* Retrieve the cost for making a voice call to a given country code.
57+
*
58+
* @param countryCode The two-character country code.
59+
*
60+
* @return A [PricingResponse] object with the pricing and network information.
61+
*/
62+
fun getOutboundVoicePriceForCountry(countryCode: String): PricingResponse =
63+
client.getVoicePrice(countryCode)
64+
65+
/**
66+
* Retrieve the cost for sending an SMS to a given prefix.
67+
*
68+
* @param prefix The prefix of the phone number.
69+
*
70+
* @return The pricing and network information for each country that uses the prefix.
71+
*/
72+
fun getOutboundSmsPriceForPrefix(prefix: String): List<PricingResponse> =
73+
client.getPrefixPrice(ServiceType.SMS, prefix).countries
74+
75+
/**
76+
* Retrieve the cost for making a voice call to a given prefix.
77+
*
78+
* @param prefix The prefix of the phone number.
79+
*
80+
* @return The pricing and network information for each country that uses the prefix.
81+
*/
82+
fun getOutboundVoicePriceForPrefix(prefix: String): List<PricingResponse> =
83+
client.getPrefixPrice(ServiceType.VOICE, prefix).countries
84+
}

src/main/kotlin/com/vonage/client/kt/Vonage.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ class Vonage(config: VonageClient.Builder.() -> Unit) {
8888
*/
8989
val numberVerification = NumberVerification(client.numberVerificationClient)
9090

91+
/**
92+
* Access to the Vonage Pricing API.
93+
*
94+
* @return The [Pricing] client.
95+
* @since 1.1.0
96+
*/
97+
val pricing = Pricing(client.accountClient)
98+
9199
/**
92100
* Access to the Vonage Redact API.
93101
*
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Copyright 2024 Vonage
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.vonage.client.kt
17+
18+
import com.vonage.client.account.Network
19+
import com.vonage.client.account.PricingResponse
20+
import kotlin.test.*
21+
22+
class PricingTest : AbstractTest() {
23+
private val client = vonage.pricing
24+
private val authType = AuthType.API_KEY_SECRET_HEADER
25+
private val countryCode = "CA"
26+
private val mobileNetwork = mapOf(
27+
"type" to "mobile",
28+
"price" to "0.00590000",
29+
"currency" to currency,
30+
"mcc" to "302",
31+
"mnc" to "530",
32+
"networkCode" to "302530",
33+
"networkName" to "Keewaytinook Okimakanak"
34+
)
35+
private val canada = mapOf(
36+
"countryName" to "Canada",
37+
"countryDisplayName" to "Canada",
38+
"countryCode" to countryCode,
39+
"currency" to "EUR",
40+
"defaultPrice" to "0.00620000",
41+
"dialingPrefix" to "1",
42+
"networks" to listOf(mobileNetwork)
43+
)
44+
private val allCountries = mapOf(
45+
"count" to 243,
46+
"countries" to listOf(canada, emptyMap())
47+
)
48+
49+
private fun assertEqualsSampleMobileNetwork(parsed: Network) {
50+
assertEquals(Network.Type.MOBILE, parsed.type)
51+
assertEquals(0.00590000, parsed.price.toDouble())
52+
assertEquals(currency, parsed.currency)
53+
assertEquals("302", parsed.mcc)
54+
assertEquals("530", parsed.mnc)
55+
assertEquals("302530", parsed.code)
56+
assertEquals("Keewaytinook Okimakanak", parsed.name)
57+
}
58+
59+
private fun assertEqualsEmptyNetwork(parsed: Network) {
60+
assertNotNull(parsed)
61+
assertNull(parsed.name)
62+
assertNull(parsed.code)
63+
assertNull(parsed.currency)
64+
assertNull(parsed.mcc)
65+
assertNull(parsed.mnc)
66+
assertNull(parsed.price)
67+
assertNull(parsed.type)
68+
}
69+
70+
private fun assertEqualsSampleCountry(parsed: PricingResponse) {
71+
assertEquals("EUR", parsed.currency)
72+
val country = parsed.country
73+
assertEquals("Canada", country.name)
74+
assertEquals("Canada", country.displayName)
75+
assertEquals("CA", country.code)
76+
assertEquals(0.00620000, parsed.defaultPrice.toDouble())
77+
assertEquals("1", parsed.dialingPrefix)
78+
assertEquals(1, parsed.networks.size)
79+
assertEqualsSampleMobileNetwork(parsed.networks[0])
80+
}
81+
82+
private fun assertEqualsEmptyCountry(parsed: PricingResponse) {
83+
assertNotNull(parsed)
84+
assertNull(parsed.currency)
85+
val country = parsed.country
86+
assertNotNull(country)
87+
assertNull(country.name)
88+
assertNull(country.displayName)
89+
assertNull(country.code)
90+
assertNull(parsed.defaultPrice)
91+
assertNull(parsed.dialingPrefix)
92+
assertNull(parsed.networks)
93+
}
94+
95+
@Test
96+
fun `list all outbound prices`() {
97+
val baseUrl = "/account/get-full-pricing/outbound"
98+
mockGet("$baseUrl/sms", authType = authType, expectedResponseParams = allCountries)
99+
100+
val smsResponse = client.listOutboundSmsPrices()
101+
assertNotNull(smsResponse)
102+
assertEquals(2, smsResponse.size)
103+
assertEqualsSampleCountry(smsResponse[0])
104+
assertEqualsEmptyCountry(smsResponse[1])
105+
106+
mockGet("$baseUrl/voice", authType = authType, expectedResponseParams = allCountries)
107+
assertEquals(smsResponse, client.listOutboundVoicePrices())
108+
}
109+
110+
@Test
111+
fun `get outbound price for country`() {
112+
val baseUrl = "/account/get-pricing/outbound"
113+
mockGet("$baseUrl/sms", authType = authType, expectedResponseParams = canada)
114+
115+
val smsResponse = client.getOutboundSmsPrice(countryCode)
116+
assertNotNull(smsResponse)
117+
assertEqualsSampleCountry(smsResponse)
118+
119+
mockGet("$baseUrl/voice", authType = authType, expectedResponseParams = canada)
120+
assertEquals(smsResponse, client.getOutboundVoicePriceForCountry(countryCode))
121+
}
122+
123+
@Test
124+
fun `get outbound price for prefix`() {
125+
val prefix = "44"
126+
val baseUrl = "/account/get-prefix-pricing/outbound"
127+
mockGet("$baseUrl/sms", authType = authType,
128+
expectedQueryParams = mapOf("prefix" to prefix),
129+
expectedResponseParams = allCountries
130+
)
131+
132+
val smsResponse = client.getOutboundSmsPriceForPrefix(prefix)
133+
assertNotNull(smsResponse)
134+
assertEquals(2, smsResponse.size)
135+
assertEqualsSampleCountry(smsResponse[0])
136+
assertEqualsEmptyCountry(smsResponse[1])
137+
138+
mockGet("$baseUrl/voice", authType = authType,
139+
expectedQueryParams = mapOf("prefix" to prefix),
140+
expectedResponseParams = allCountries
141+
)
142+
assertEquals(smsResponse, client.getOutboundVoicePriceForPrefix(prefix))
143+
}
144+
}

src/test/kotlin/com/vonage/client/kt/VonageTest.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package com.vonage.client.kt
1717

1818
import com.vonage.client.HttpWrapper
19-
import com.vonage.client.VonageClient
2019
import org.apache.commons.lang3.reflect.FieldUtils
2120
import kotlin.test.*
2221

0 commit comments

Comments
 (0)