Skip to content

Commit fde8010

Browse files
onairmarcEncoreBotCopilot
authored
Add Payment Method Support (#55)
Co-authored-by: EncoreBot <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent fd1e2a5 commit fde8010

21 files changed

+2086
-59
lines changed

.git-blame-ignore-revs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ f4c2516ff9d77ec117fe5604335dcb648a2e90e6
2222
b2113ed15c0661c82c77689e190659ba0527896e
2323
049b2dbb985bb2a708282c479c983308f3b705de
2424
3983fb6ff509c0ae81e943aaf440a4bb7eca7147
25+
d97004494d4c686b50d44666de9fb933346ce856
26+
8fe71bd77c474858db4a4c1278f740cb8ce4032e

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,28 @@ $updated = Stripe::customer()
193193
->save();
194194
```
195195

196+
### Payment Method Management
197+
198+
```php
199+
use EncoreDigitalGroup\Stripe\Stripe;
200+
use EncoreDigitalGroup\Stripe\Enums\PaymentMethodType;
201+
use EncoreDigitalGroup\Stripe\Objects\Payment\StripePaymentMethod;
202+
203+
// Create and attach payment method to customer
204+
$customer = Stripe::customer()->get('cus_123');
205+
$paymentMethod = StripePaymentMethod::make()
206+
->withType(PaymentMethodType::Card);
207+
208+
$customer->addPaymentMethod($paymentMethod);
209+
210+
// List customer's payment methods
211+
$paymentMethods = $customer->paymentMethods();
212+
213+
// Access individual payment method
214+
$paymentMethod = $paymentMethods->first();
215+
echo $paymentMethod->type()?->value; // "card"
216+
```
217+
196218
### Product & Price Management
197219

198220
```php
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
/*
4+
* Copyright (c) 2025. Encore Digital Group.
5+
* All Right Reserved.
6+
*/
7+
8+
namespace EncoreDigitalGroup\Stripe\Enums;
9+
10+
enum PaymentIntentCaptureMethod: string
11+
{
12+
case Automatic = "automatic";
13+
case AutomaticAsync = "automatic_async";
14+
case Manual = "manual";
15+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
/*
4+
* Copyright (c) 2025. Encore Digital Group.
5+
* All Right Reserved.
6+
*/
7+
8+
namespace EncoreDigitalGroup\Stripe\Enums;
9+
10+
enum PaymentIntentConfirmationMethod: string
11+
{
12+
case Automatic = "automatic";
13+
case Manual = "manual";
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
/*
4+
* Copyright (c) 2025. Encore Digital Group.
5+
* All Right Reserved.
6+
*/
7+
8+
namespace EncoreDigitalGroup\Stripe\Enums;
9+
10+
enum PaymentIntentSetupFutureUsage: string
11+
{
12+
case OnSession = "on_session";
13+
case OffSession = "off_session";
14+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/*
4+
* Copyright (c) 2025. Encore Digital Group.
5+
* All Right Reserved.
6+
*/
7+
8+
namespace EncoreDigitalGroup\Stripe\Enums;
9+
10+
enum PaymentIntentStatus: string
11+
{
12+
case RequiresPaymentMethod = "requires_payment_method";
13+
case RequiresConfirmation = "requires_confirmation";
14+
case RequiresAction = "requires_action";
15+
case Processing = "processing";
16+
case RequiresCapture = "requires_capture";
17+
case Canceled = "canceled";
18+
case Succeeded = "succeeded";
19+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
/*
4+
* Copyright (c) 2025. Encore Digital Group.
5+
* All Right Reserved.
6+
*/
7+
8+
namespace EncoreDigitalGroup\Stripe\Enums;
9+
10+
enum PaymentMethodType: string
11+
{
12+
case AcssDebit = "acss_debit";
13+
case Affirm = "affirm";
14+
case AfterpayClearpay = "afterpay_clearpay";
15+
case Alipay = "alipay";
16+
case AmazonPay = "amazon_pay";
17+
case AuBecsDebit = "au_becs_debit";
18+
case BacsDebit = "bacs_debit";
19+
case Bancontact = "bancontact";
20+
case Blik = "blik";
21+
case Boleto = "boleto";
22+
case Card = "card";
23+
case CardPresent = "card_present";
24+
case Cashapp = "cashapp";
25+
case CustomerBalance = "customer_balance";
26+
case Eps = "eps";
27+
case Fpx = "fpx";
28+
case Giropay = "giropay";
29+
case Grabpay = "grabpay";
30+
case Ideal = "ideal";
31+
case InteracPresent = "interac_present";
32+
case Klarna = "klarna";
33+
case Konbini = "konbini";
34+
case Link = "link";
35+
case Mobilepay = "mobilepay";
36+
case Multibanco = "multibanco";
37+
case Oxxo = "oxxo";
38+
case P24 = "p24";
39+
case Paynow = "paynow";
40+
case Paypal = "paypal";
41+
case Pix = "pix";
42+
case Promptpay = "promptpay";
43+
case RevolutPay = "revolut_pay";
44+
case SepaDebit = "sepa_debit";
45+
case Sofort = "sofort";
46+
case Swish = "swish";
47+
case Twint = "twint";
48+
case UsBankAccount = "us_bank_account";
49+
case WechatPay = "wechat_pay";
50+
case Zip = "zip";
51+
}

src/php/Objects/Customer/StripeCustomer.php

Lines changed: 62 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
namespace EncoreDigitalGroup\Stripe\Objects\Customer;
99

1010
use EncoreDigitalGroup\StdLib\Exceptions\NullExceptions\ClassPropertyNullException;
11+
use EncoreDigitalGroup\StdLib\Exceptions\NullExceptions\VariableNullException;
1112
use EncoreDigitalGroup\StdLib\Objects\Support\Types\Arr;
13+
use EncoreDigitalGroup\Stripe\Objects\Payment\StripePaymentMethod;
1214
use EncoreDigitalGroup\Stripe\Objects\Subscription\StripeSubscription;
1315
use EncoreDigitalGroup\Stripe\Objects\Support\StripeAddress;
1416
use EncoreDigitalGroup\Stripe\Services\StripeCustomerService;
17+
use EncoreDigitalGroup\Stripe\Services\StripePaymentMethodService;
1518
use EncoreDigitalGroup\Stripe\Services\StripeSubscriptionService;
1619
use EncoreDigitalGroup\Stripe\Support\Traits\HasGet;
1720
use EncoreDigitalGroup\Stripe\Support\Traits\HasSave;
@@ -37,6 +40,9 @@ class StripeCustomer
3740
/** @var ?Collection<StripeSubscription> */
3841
private ?Collection $subscriptions = null;
3942

43+
/** @var ?Collection<StripePaymentMethod> */
44+
private ?Collection $paymentMethods = null;
45+
4046
/**
4147
* Create a StripeCustomer instance from a Stripe API Customer object
4248
*/
@@ -51,7 +57,7 @@ public static function fromStripeObject(Customer $stripeCustomer): self
5157
if (isset($stripeCustomer->address)) {
5258
/** @var StripeObject $stripeAddress */
5359
$stripeAddress = $stripeCustomer->address;
54-
$instance = $instance->withAddress(self::extractAddress($stripeAddress));
60+
$instance = $instance->withAddress(StripeAddress::fromStripeObject($stripeAddress));
5561
}
5662

5763
if ($stripeCustomer->description ?? null) {
@@ -83,39 +89,13 @@ public static function fromStripeObject(Customer $stripeCustomer): self
8389
return $instance;
8490
}
8591

86-
private static function extractAddress(StripeObject $stripeAddress): StripeAddress
87-
{
88-
$address = StripeAddress::make();
89-
90-
if ($stripeAddress->line1 ?? null) {
91-
$address = $address->withLine1($stripeAddress->line1);
92-
}
93-
if ($stripeAddress->line2 ?? null) {
94-
$address = $address->withLine2($stripeAddress->line2);
95-
}
96-
if ($stripeAddress->city ?? null) {
97-
$address = $address->withCity($stripeAddress->city);
98-
}
99-
if ($stripeAddress->state ?? null) {
100-
$address = $address->withState($stripeAddress->state);
101-
}
102-
if ($stripeAddress->postal_code ?? null) {
103-
$address = $address->withPostalCode($stripeAddress->postal_code);
104-
}
105-
if ($stripeAddress->country ?? null) {
106-
return $address->withCountry($stripeAddress->country);
107-
}
108-
109-
return $address;
110-
}
111-
11292
private static function extractShipping(StripeObject $stripeShipping): ?StripeShipping
11393
{
11494
$shippingAddress = null;
11595
if (isset($stripeShipping->address)) {
11696
/** @var StripeObject $shippingAddressObj */
11797
$shippingAddressObj = $stripeShipping->address;
118-
$shippingAddress = self::extractAddress($shippingAddressObj);
98+
$shippingAddress = StripeAddress::fromStripeObject($shippingAddressObj);
11999
}
120100

121101
// Only create shipping if we have the required fields (address and name)
@@ -134,6 +114,60 @@ private static function extractShipping(StripeObject $stripeShipping): ?StripeSh
134114
return $shipping;
135115
}
136116

117+
/** @returns Collection<StripeSubscription> */
118+
public function subscriptions(bool $refresh = false): Collection
119+
{
120+
if ($this->subscriptions instanceof Collection && !$refresh) {
121+
return $this->subscriptions;
122+
}
123+
124+
if (is_null($this->id)) {
125+
throw new ClassPropertyNullException("id");
126+
}
127+
128+
$this->subscriptions = app(StripeSubscriptionService::class)->getAllForCustomer($this->id);
129+
130+
return $this->subscriptions;
131+
}
132+
133+
/** @returns Collection<StripePaymentMethod> */
134+
public function paymentMethods(bool $refresh = false): Collection
135+
{
136+
if ($this->paymentMethods instanceof Collection && !$refresh) {
137+
return $this->paymentMethods;
138+
}
139+
140+
if (is_null($this->id)) {
141+
throw new ClassPropertyNullException("id");
142+
}
143+
144+
$this->paymentMethods = app(StripePaymentMethodService::class)->getAllForCustomer($this->id);
145+
146+
return $this->paymentMethods;
147+
}
148+
149+
public function addPaymentMethod(StripePaymentMethod $paymentMethod): self
150+
{
151+
$paymentMethod = app(StripePaymentMethodService::class)->create($paymentMethod);
152+
$paymentMethodId = $paymentMethod->id();
153+
154+
if (is_null($paymentMethodId)) {
155+
throw new VariableNullException("paymentMethodId");
156+
}
157+
158+
if (is_null($this->id)) {
159+
throw new ClassPropertyNullException("id");
160+
}
161+
162+
app(StripePaymentMethodService::class)->attach($paymentMethodId, $this->id);
163+
164+
if (!is_null($this->paymentMethods)) {
165+
$this->paymentMethods(true);
166+
}
167+
168+
return $this;
169+
}
170+
137171
public function service(): StripeCustomerService
138172
{
139173
return app(StripeCustomerService::class);
@@ -239,20 +273,4 @@ public function shipping(): ?StripeShipping
239273
{
240274
return $this->shipping;
241275
}
242-
243-
/** @returns Collection<StripeSubscription> */
244-
public function subscriptions(bool $refresh = false): Collection
245-
{
246-
if ($this->subscriptions instanceof Collection && !$refresh) {
247-
return $this->subscriptions;
248-
}
249-
250-
if (is_null($this->id)) {
251-
throw new ClassPropertyNullException("id");
252-
}
253-
254-
$this->subscriptions = app(StripeSubscriptionService::class)->getAllForCustomer($this->id);
255-
256-
return $this->subscriptions;
257-
}
258276
}

0 commit comments

Comments
 (0)