2020use EncoreDigitalGroup \Stripe \Support \Traits \HasGet ;
2121use EncoreDigitalGroup \Stripe \Support \Traits \HasSave ;
2222use Illuminate \Support \Collection ;
23+ use InvalidArgumentException ;
2324use PHPGenesis \Common \Traits \HasMake ;
2425use Stripe \Customer ;
2526use Stripe \StripeObject ;
@@ -44,6 +45,9 @@ class StripeCustomer
4445 /** @var ?Collection<StripePaymentMethod> */
4546 private ?Collection $ paymentMethods = null ;
4647
48+ private ?bool $ hasDefaultPaymentMethod = null ;
49+ private ?string $ defaultPaymentMethod = null ;
50+
4751 /**
4852 * Create a StripeCustomer instance from a Stripe API Customer object
4953 */
@@ -55,6 +59,14 @@ public static function fromStripeObject(Customer $stripeCustomer): self
5559 $ instance = $ instance ->withId ($ stripeCustomer ->id );
5660 }
5761
62+ $ instance = self ::applyBasicProperties ($ instance , $ stripeCustomer );
63+ $ instance = self ::applyShippingIfPresent ($ instance , $ stripeCustomer );
64+
65+ return self ::applyDefaultPaymentMethod ($ instance , $ stripeCustomer );
66+ }
67+
68+ private static function applyBasicProperties (self $ instance , Customer $ stripeCustomer ): self
69+ {
5870 if (isset ($ stripeCustomer ->address )) {
5971 /** @var StripeObject $stripeAddress */
6072 $ stripeAddress = $ stripeCustomer ->address ;
@@ -74,17 +86,45 @@ public static function fromStripeObject(Customer $stripeCustomer): self
7486 }
7587
7688 if ($ stripeCustomer ->phone ?? null ) {
77- $ instance = $ instance ->withPhone ($ stripeCustomer ->phone );
89+ return $ instance ->withPhone ($ stripeCustomer ->phone );
7890 }
7991
80- if (isset ($ stripeCustomer ->shipping )) {
81- /** @var StripeObject $stripeShipping */
82- $ stripeShipping = $ stripeCustomer ->shipping ;
83- $ shipping = self ::extractShipping ($ stripeShipping );
92+ return $ instance ;
93+ }
8494
85- if ($ shipping instanceof StripeShipping) {
86- $ instance = $ instance ->withShipping ($ shipping );
87- }
95+ private static function applyShippingIfPresent (self $ instance , Customer $ stripeCustomer ): self
96+ {
97+ if (!isset ($ stripeCustomer ->shipping )) {
98+ return $ instance ;
99+ }
100+
101+ /** @var StripeObject $stripeShipping */
102+ $ stripeShipping = $ stripeCustomer ->shipping ;
103+ $ shipping = self ::extractShipping ($ stripeShipping );
104+
105+ if ($ shipping instanceof StripeShipping) {
106+ return $ instance ->withShipping ($ shipping );
107+ }
108+
109+ return $ instance ;
110+ }
111+
112+ private static function applyDefaultPaymentMethod (self $ instance , Customer $ stripeCustomer ): self
113+ {
114+ if (!isset ($ stripeCustomer ->invoice_settings )) {
115+ return $ instance ;
116+ }
117+
118+ $ defaultPaymentMethod = $ stripeCustomer ->invoice_settings ->default_payment_method ?? null ;
119+
120+ if (is_string ($ defaultPaymentMethod )) {
121+ $ instance ->defaultPaymentMethod = $ defaultPaymentMethod ;
122+ $ instance ->hasDefaultPaymentMethod = true ;
123+ }
124+
125+ if (is_object ($ defaultPaymentMethod )) {
126+ $ instance ->defaultPaymentMethod = $ defaultPaymentMethod ->id ;
127+ $ instance ->hasDefaultPaymentMethod = true ;
88128 }
89129
90130 return $ instance ;
@@ -178,6 +218,39 @@ public function createSetupIntent(): StripeSetupIntent
178218 return StripeSetupIntent::make ()->withCustomer ($ this ->id );
179219 }
180220
221+ public function hasDefaultPaymentMethod (): bool
222+ {
223+ if (is_null ($ this ->id )) {
224+ throw new ClassPropertyNullException ("id " );
225+ }
226+
227+ if (!is_null ($ this ->hasDefaultPaymentMethod )) {
228+ return $ this ->hasDefaultPaymentMethod ;
229+ }
230+
231+ $ this ->hasDefaultPaymentMethod = $ this ->service ()->hasDefaultPaymentMethod ($ this ->id );
232+
233+ return $ this ->hasDefaultPaymentMethod ;
234+ }
235+
236+ public function save (): self
237+ {
238+ if (!is_null ($ this ->defaultPaymentMethod )) {
239+ if (is_null ($ this ->id )) {
240+ throw new ClassPropertyNullException ("id " );
241+ }
242+
243+ $ paymentMethods = $ this ->paymentMethods ();
244+ $ paymentMethodExists = $ paymentMethods ->contains (fn ($ pm ): bool => $ pm ->id () === $ this ->defaultPaymentMethod );
245+
246+ if (!$ paymentMethodExists ) {
247+ throw new InvalidArgumentException ("Payment method {$ this ->defaultPaymentMethod } is not attached to customer {$ this ->id }" );
248+ }
249+ }
250+
251+ return is_null ($ this ->id ) ? $ this ->service ()->create ($ this ) : $ this ->service ()->update ($ this ->id , $ this );
252+ }
253+
181254 public function service (): StripeCustomerService
182255 {
183256 return app (StripeCustomerService::class);
@@ -195,6 +268,12 @@ public function toArray(): array
195268 "shipping " => $ this ->shipping ?->toArray(),
196269 ];
197270
271+ if (!is_null ($ this ->defaultPaymentMethod )) {
272+ $ array ["invoice_settings " ] = [
273+ "default_payment_method " => $ this ->defaultPaymentMethod ,
274+ ];
275+ }
276+
198277 return Arr::whereNotNull ($ array );
199278 }
200279
@@ -248,6 +327,13 @@ public function withShipping(StripeShipping $shipping): self
248327 return $ this ;
249328 }
250329
330+ public function withDefaultPaymentMethod (string $ defaultPaymentMethod ): self
331+ {
332+ $ this ->defaultPaymentMethod = $ defaultPaymentMethod ;
333+
334+ return $ this ;
335+ }
336+
251337 // Getter methods
252338 public function id (): ?string
253339 {
0 commit comments