@@ -5,6 +5,7 @@ import java.time.OffsetDateTime
55import akka .http .scaladsl .HttpExt
66import akka .http .scaladsl .model .Uri
77import akka .stream .Materializer
8+ import cats .syntax .either ._
89import com .typesafe .scalalogging .LazyLogging
910import defaults ._
1011import 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