Skip to content

Commit 10f5821

Browse files
committed
Add Product ADT for child product of Plan objects
1 parent 0ae74cb commit 10f5821

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed

src/main/scala/org/mdedetrich/stripe/v1/Plans.scala

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import java.time.OffsetDateTime
55
import akka.http.scaladsl.HttpExt
66
import akka.http.scaladsl.model.Uri
77
import akka.stream.Materializer
8+
import cats.syntax.either._
89
import com.typesafe.scalalogging.LazyLogging
910
import defaults._
1011
import enumeratum._
@@ -133,6 +134,84 @@ object Plans extends LazyLogging {
133134
x.statementDescriptor,
134135
x.trialPeriodDays))
135136

137+
sealed abstract class Product
138+
139+
object Product {
140+
import io.circe._
141+
import io.circe.syntax._
142+
143+
case class ProductId(id: String) extends Product
144+
145+
/**
146+
* @see https://stripe.com/docs/api#create_plan
147+
* @param id The identifier for the product.
148+
* Must be unique. If not provided, an identifier will be randomly
149+
* generated.
150+
* @param name The product’s name, meant to be displayable to the customer.
151+
* @param metadata
152+
* @param statementDescriptor An arbitrary string to be displayed on your
153+
* customer’s credit card statement. This may be up to 22
154+
* characters. As an example, if your website is RunClub and the
155+
* item you’re charging for is your Silver Plan, you may want to
156+
* specify a [[statementDescriptor]] of RunClub Silver Plan. The
157+
* statement description may not include `<>"'` characters, and will
158+
* appear on your customer’s statement in capital letters. Non-ASCII
159+
* characters are automatically stripped. While most banks display
160+
* this information consistently, some may display it incorrectly or
161+
* not at all.
162+
*
163+
* @throws StatementDescriptorTooLong - If [[statementDescriptor]] is longer than 22 characters
164+
* @throws StatementDescriptorInvalidCharacter - If [[statementDescriptor]] has an invalid character
165+
*/
166+
case class ServiceProduct(
167+
id: Option[String],
168+
name: String,
169+
metadata: Option[Map[String, String]],
170+
statementDescriptor: Option[String]
171+
) extends Product {
172+
statementDescriptor match {
173+
case Some(sD) if sD.length > 22 =>
174+
throw StatementDescriptorTooLong(sD.length)
175+
case Some(sD) if sD.contains("<") =>
176+
throw StatementDescriptorInvalidCharacter("<")
177+
case Some(sD) if sD.contains(">") =>
178+
throw StatementDescriptorInvalidCharacter(">")
179+
case Some(sD) if sD.contains("\"") =>
180+
throw StatementDescriptorInvalidCharacter("\"")
181+
case Some(sD) if sD.contains("\'") =>
182+
throw StatementDescriptorInvalidCharacter("\'")
183+
case _ =>
184+
}
185+
}
186+
187+
implicit val planProductDecoder: Decoder[Product] = Decoder.instance[Product] { p =>
188+
p.as[JsonObject] match {
189+
case Left(_) =>
190+
p.as[String].map(ProductId.apply)
191+
case Right(_) =>
192+
val decoder: Decoder[ServiceProduct] = Decoder.forProduct4(
193+
"id",
194+
"name",
195+
"metadata",
196+
"statement_descriptor"
197+
)(ServiceProduct.apply)
198+
decoder.apply(p)
199+
}
200+
}
201+
202+
implicit val planProductEncoder: Encoder[Product] = Encoder.instance[Product] {
203+
case ProductId(id) => id.asJson
204+
case service: ServiceProduct =>
205+
val encoder: Encoder[ServiceProduct] = Encoder.forProduct4(
206+
"id",
207+
"name",
208+
"metadata",
209+
"statement_descriptor"
210+
)(x => ServiceProduct.unapply(x).get)
211+
encoder.apply(service)
212+
}
213+
}
214+
136215
/**
137216
* @see https://stripe.com/docs/api#create_plan
138217
* @param id An identifier randomly generated by Stripe.

0 commit comments

Comments
 (0)