Skip to content

Commit b9b7024

Browse files
committed
Support Afterpay through Stripe
1 parent 6c2c052 commit b9b7024

File tree

4 files changed

+120
-14
lines changed

4 files changed

+120
-14
lines changed

README.md

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,21 @@ $payum = (new PayumBuilder)
2727
'factory' => 'stripe_elements',
2828
'publishable_key' => 'Your Public Key',
2929
'secret_key' => 'Your Private Key',
30+
'img_url' => 'https://path/to/logo/image.jpg',
31+
])
32+
33+
->addGateway('stripe_afterpay', [
34+
'factory' => 'stripe_afterpay',
35+
'publishable_key' => 'Your Public Key',
36+
'secret_key' => 'Your Private Key',
37+
'img_url' => 'https://path/to/logo/image.jpg',
3038
])
3139

3240
->getPayum()
3341
;
3442
```
3543

36-
### Request payment
44+
### Request card payment
3745

3846
```php
3947
<?php
@@ -51,7 +59,7 @@ $payment->setCurrencyCode($currency);
5159
$payment->setTotalAmount(100); // Total cents
5260
$payment->setDescription(substr($description, 0, 45));
5361
$payment->setDetails([
54-
'local' => [
62+
'local' => [
5563
'email' => $email, // Used for the customer to be able to save payment details
5664
],
5765
]);
@@ -63,6 +71,59 @@ header("Location: " . $url);
6371
die();
6472
```
6573

74+
### Request Afterpay payment
75+
76+
Afterpay requires more information about the customer to process the payment
77+
78+
```php
79+
<?php
80+
81+
use Payum\Core\Request\Capture;
82+
83+
$storage = $payum->getStorage(\Payum\Core\Model\Payment::class);
84+
$request = [
85+
'invoice_id' => 100,
86+
];
87+
88+
$payment = $storage->create();
89+
$payment->setNumber(uniqid());
90+
$payment->setCurrencyCode($currency);
91+
$payment->setTotalAmount(100); // Total cents
92+
$payment->setDescription(substr($description, 0, 45));
93+
$payment->setDetails([
94+
'local' => [
95+
'email' => $email, // Used for the customer to be able to save payment details
96+
],
97+
'shipping' => [
98+
'name' => 'Firstname Lastname',
99+
'address' => [
100+
'line1' => 'Address Line 1',
101+
'city' => 'Address City',
102+
'state' => 'Address State',
103+
'country' => 'Address Country',
104+
'postal_code' => 'Address Postal Code',
105+
],
106+
],
107+
'billing' => [
108+
'name' => trim($shopper['first_name'] . ' ' . $shopper['last_name']),
109+
'email' => $shopper['email'],
110+
'address' => [
111+
'line1' => 'Address Line 1',
112+
'city' => 'Address City',
113+
'state' => 'Address State',
114+
'country' => 'Address Country',
115+
'postal_code' => 'Address Postal Code',
116+
],
117+
],
118+
]);
119+
$storage->setInternalDetails($payment, $request);
120+
121+
$captureToken = $payum->getTokenFactory()->createCaptureToken('stripe_afterpay', $payment, 'done.php');
122+
$url = $captureToken->getTargetUrl();
123+
header("Location: " . $url);
124+
die();
125+
```
126+
66127
### Check it worked
67128

68129
```php
@@ -80,11 +141,11 @@ $gateway->execute($status = new GetHumanStatus($model));
80141

81142
// using shortcut
82143
if ($status->isNew() || $status->isCaptured() || $status->isAuthorized()) {
83-
// success
144+
// success
84145
} elseif ($status->isPending()) {
85-
// most likely success, but you have to wait for a push notification.
146+
// most likely success, but you have to wait for a push notification.
86147
} elseif ($status->isFailed() || $status->isCanceled()) {
87-
// the payment has failed or user canceled it.
148+
// the payment has failed or user canceled it.
88149
}
89150
```
90151

src/Action/ObtainNonceAction.php

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ class ObtainNonceAction implements ActionInterface, GatewayAwareInterface {
2121
* @var string
2222
*/
2323
protected $templateName;
24+
protected $use_afterpay;
2425

2526
/**
2627
* @param string $templateName
2728
*/
28-
public function __construct(string $templateName) {
29+
public function __construct(string $templateName, bool $use_afterpay) {
2930
$this->templateName = $templateName;
31+
$this->use_afterpay = $use_afterpay;
3032
}
3133

3234
/**
@@ -41,31 +43,46 @@ public function execute($request) {
4143
if ($model['card']) {
4244
throw new LogicException('The token has already been set.');
4345
}
46+
$uri = \League\Uri\Http::createFromServer($_SERVER);
4447

4548
$getHttpRequest = new GetHttpRequest();
4649
$this->gateway->execute($getHttpRequest);
47-
if ($getHttpRequest->method == 'POST' && isset($getHttpRequest->request['payment_intent'])) {
50+
// Received payment intent information from Stripe
51+
if (isset($getHttpRequest->request['payment_intent'])) {
4852
$model['nonce'] = $getHttpRequest->request['payment_intent'];
4953
return;
5054
}
51-
52-
$model['stripePaymentIntent'] = \Stripe\PaymentIntent::create([
55+
$afterPayDetails = [];
56+
if ($this->use_afterpay) { // Afterpay order
57+
$afterPayDetails = [
58+
'confirm' => true,
59+
'payment_method_types' => ['afterpay_clearpay'],
60+
'shipping' => $model['shipping'],
61+
'payment_method_data' => [
62+
'type' => 'afterpay_clearpay',
63+
'billing_details' => $model['billing'],
64+
],
65+
'return_url' => $uri->withPath('')->withFragment('')->withQuery('')->__toString() . $getHttpRequest->uri,
66+
];
67+
}
68+
$paymentIntentData = array_merge([
5369
'amount' => round($model['amount'] * pow(10, $model['currencyDigits'])),
70+
'payment_method_types' => $model['payment_method_types'] ?? ['card'],
5471
'currency' => $model['currency'],
5572
'metadata' => ['integration_check' => 'accept_a_payment'],
5673
'statement_descriptor' => $model['statement_descriptor_suffix'],
5774
'description' => $model['description'],
58-
'automatic_payment_methods' => [
59-
'enabled' => 'true',
60-
],
61-
]);
75+
], $afterPayDetails);
6276

77+
$model['stripePaymentIntent'] = \Stripe\PaymentIntent::create($paymentIntentData);
6378
$this->gateway->execute($renderTemplate = new RenderTemplate($this->templateName, array(
6479
'amount' => $model['currencySymbol'] . ' ' . number_format($model['amount'], $model['currencyDigits']),
6580
'client_secret' => $model['stripePaymentIntent']->client_secret,
6681
'publishable_key' => $model['publishable_key'],
6782
'actionUrl' => $getHttpRequest->uri,
6883
'imgUrl' => $model['img_url'],
84+
'use_afterpay' => $this->use_afterpay ? "true" : "false",
85+
'billing' => $model['billing'] ?? [],
6986
)));
7087

7188
throw new HttpResponse($renderTemplate->getResult());

src/Resources/views/Action/obtain_nonce.html.twig

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,33 @@
8484
// prompt the user to enter authentication details without leaving your page.
8585
var payWithCard = function(stripe) {
8686
loading(true);
87+
// Afterpay?
88+
if ({{ use_afterpay }}) {
89+
stripe.confirmAfterpayClearpayPayment(
90+
'{{ client_secret }}',
91+
{
92+
payment_method: {
93+
billing_details: {
94+
email: "{{ billing.email }}",
95+
name: "{{ billing.name }}", // Double quotes less likely to be in a name
96+
address: {
97+
line1: "{{ billing.address.line1 }}",
98+
city: "{{ billing.address.city }}",
99+
state: "{{ billing.address.state }}",
100+
country: "{{ billing.address.country }}",
101+
postal_code: "{{ billing.address.postal_code }}",
102+
},
103+
},
104+
},
105+
return_url: window.location.href,
106+
}
107+
).then(function(result) {
108+
if (result.error) {
109+
// Inform the customer that there was an error.
110+
}
111+
});
112+
return
113+
}
87114
stripe
88115
.confirmPayment({
89116
elements,

src/StripeElementsGatewayFactory.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ protected function populateConfig(ArrayObject $config)
2727
'payum.action.status' => new StatusAction(),
2828
'payum.action.convert_payment' => new ConvertPaymentAction(),
2929
'payum.action.obtain_nonce' => function (ArrayObject $config) {
30-
return new ObtainNonceAction($config['payum.template.obtain_nonce']);
30+
return new ObtainNonceAction($config['payum.template.obtain_nonce'], $config['type'] == 'stripe_afterpay');
3131
},
3232
]);
3333

@@ -44,6 +44,7 @@ protected function populateConfig(ArrayObject $config)
4444
return new Api((array) $config, $config['payum.http_client'], $config['httplug.message_factory']);
4545
};
4646
}
47+
$config['use_afterpay'] = $config['type'] == 'stripe_afterpay';
4748
$payumPaths = $config['payum.paths'];
4849
$payumPaths['PayumStripeElements'] = __DIR__ . '/Resources/views';
4950
$config['payum.paths'] = $payumPaths;

0 commit comments

Comments
 (0)