-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add authorize, use getAfterUrl instead of getTargetUrl and Sync a pay…
…ment before getting it Status
- Loading branch information
Showing
57 changed files
with
2,298 additions
and
525 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,192 +2,10 @@ | |
|
||
See https://stripe.com/docs/payments/checkout for more information. | ||
|
||
## Get it started | ||
|
||
First get [your credentials](../stripe-credentials.md) from Stripe dashboard. | ||
|
||
> The following example is the basic Payum implementation | ||
> (see [documentation of Payum](https://github.com/Payum/Payum/blob/master/docs/get-it-started.md) for more information) | ||
### config.php | ||
|
||
```php | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
$loader = require_once( __DIR__.'/vendor/autoload.php'); | ||
|
||
use Payum\Core\GatewayFactoryInterface; | ||
use FluxSE\PayumStripe\StripeCheckoutSessionGatewayFactory; | ||
use Payum\Core\PayumBuilder; | ||
use Payum\Core\Payum; | ||
|
||
/** @var Payum $payum */ | ||
$payum = (new PayumBuilder()) | ||
->addDefaultStorages() | ||
->addGatewayFactory('stripe_checkout_session', function(array $config, GatewayFactoryInterface $coreGatewayFactory) { | ||
return new StripeCheckoutSessionGatewayFactory($config, $coreGatewayFactory); | ||
}) | ||
->addGateway('stripe_checkout_session', [ | ||
'factory' => 'stripe_checkout_session', | ||
'publishable_key' => 'pk_test_abcdefghijklmnopqrstuvwx', | ||
'secret_key' => 'sk_test_abcdefghijklmnopqrstuvwx', | ||
'webhook_secret_keys' => [ | ||
'whsec_abcdefghijklmnopqrstuvwxyz012345' | ||
], | ||
]) | ||
->getPayum() | ||
; | ||
``` | ||
|
||
### prepare.php | ||
|
||
```php | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
include __DIR__.'/config.php'; | ||
|
||
use Payum\Core\Model\Payment; | ||
|
||
$gatewayName = 'stripe_checkout_session'; | ||
|
||
$storage = $payum->getStorage(Payment::class); | ||
|
||
/** @var Payment $payment */ | ||
$payment = $storage->create(); | ||
$payment->setNumber(uniqid()); | ||
$payment->setCurrencyCode('EUR'); | ||
$payment->setTotalAmount(123); // 1.23 EUR | ||
$payment->setDescription('A description'); | ||
$payment->setClientId('anId'); | ||
$payment->setClientEmail('[email protected]'); | ||
$payment->setDetails([]); | ||
|
||
$storage->update($payment); | ||
|
||
$tokenFactory = $payum->getTokenFactory(); | ||
$captureToken = $tokenFactory->createCaptureToken($gatewayName, $payment, 'done.php'); | ||
|
||
header("Location: ".$captureToken->getTargetUrl()); | ||
``` | ||
|
||
### capture.php | ||
|
||
```php | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
use Payum\Core\Reply\HttpResponse; | ||
use Payum\Core\Request\Capture; | ||
use Payum\Core\Reply\HttpRedirect; | ||
|
||
include __DIR__.'/config.php'; | ||
|
||
$token = $payum->getHttpRequestVerifier()->verify($_REQUEST); | ||
$gateway = $payum->getGateway($token->getGatewayName()); | ||
|
||
if ($reply = $gateway->execute(new Capture($token), true)) { | ||
if ($reply instanceof HttpRedirect) { | ||
header("Location: ".$reply->getUrl()); | ||
die(); | ||
} | ||
if ($reply instanceof HttpResponse) { | ||
echo $reply->getContent(); | ||
die(); | ||
} | ||
|
||
throw new \LogicException('Unsupported reply', null, $reply); | ||
} | ||
|
||
$payum->getHttpRequestVerifier()->invalidate($token); | ||
|
||
header("Location: ".$token->getAfterUrl()); | ||
``` | ||
|
||
### done.php | ||
|
||
```php | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
use Payum\Core\Request\GetHumanStatus; | ||
|
||
include __DIR__.'/config.php'; | ||
|
||
$token = $payum->getHttpRequestVerifier()->verify($_REQUEST); | ||
$gateway = $payum->getGateway($token->getGatewayName()); | ||
|
||
// you can invalidate the token. The url could not be requested any more. | ||
// $payum->getHttpRequestVerifier()->invalidate($token); | ||
|
||
// Once you have token you can get the model from the storage directly. | ||
//$identity = $token->getDetails(); | ||
//$payment = $payum->getStorage($identity->getClass())->find($identity); | ||
|
||
// or Payum can fetch the model for you while executing a request (Preferred). | ||
$gateway->execute($status = new GetHumanStatus($token)); | ||
$payment = $status->getFirstModel(); | ||
|
||
header('Content-Type: application/json'); | ||
echo json_encode([ | ||
'status' => $status->getValue(), | ||
'order' => [ | ||
'total_amount' => $payment->getTotalAmount(), | ||
'currency_code' => $payment->getCurrencyCode(), | ||
'details' => $payment->getDetails(), | ||
], | ||
], JSON_PRETTY_PRINT); | ||
``` | ||
|
||
## Webhooks | ||
|
||
For generic info on Stripe webhooks read this : | ||
https://stripe.com/docs/webhooks | ||
|
||
### How the webhooks are handle into this gateway ? | ||
|
||
The starting point is always an `Action` with Payum and generically you have to use `Notify*Action` to handle webhooks. | ||
|
||
Because we have to set a static url on Stripe backend (eg: without any token variable params), | ||
we have to use what Payum is calling a `NotifyUnsafe`, it's a `Notify` with a `null` `Token`. | ||
You can find this action here : [`NotifyAction.php`](../../src/Action/NotifyAction.php). | ||
If the token is null then we will try to handle a webhook, and if a token is detected | ||
then it's a normal `Notify` so we must handle a `Sync` to refresh a payment details. | ||
|
||
#### Resolving a webhook : `NotifyUnsafe` | ||
|
||
The [`NotifyAction.php`](../../src/Action/NotifyAction.php) will ask for 2 other actions to : | ||
|
||
1. Resolve the webhook event, meaning : | ||
- retrieve the Stripe signature in the request headers. | ||
- try to construct the webhook `Event` object, checking it with the webhook secret key. | ||
2. Give this resolved `Event` to an `Action` able to consume this `Event`. | ||
|
||
So if you want to consume another webhook event type, you just need to create an `Action` | ||
extending [`FluxSE\PayumStripe\Action\Api\WebhookEvent\AbstractWebhookEventAction`](../../src/Action/Api/WebhookEvent/AbstractWebhookEventAction.php). | ||
Examples available into the [`src/Action/Api/WebhookEvent/`](../../src/Action/Api/WebhookEvent) folder. | ||
|
||
## Subscription handling | ||
|
||
Payum don't have php `Interfaces` to handle subscription, that's why subscriptions should be | ||
managed by yourself. There is maybe a composer packages which fit your need, | ||
but you will have to build the interface between your subscription `Model` class and `Payum`. | ||
|
||
Usually you will have to build a `ConvertPaymentAction` like this one : [ConvertPaymentAction.php](https://github.com/FLUX-SE/SyliusPayumStripePlugin/blob/master/src/Action/ConvertPaymentAction.php) | ||
customizing the `supports` method to fit your need and provide the right `$details` array. | ||
|
||
Example : https://stripe.com/docs/payments/checkout/subscriptions/starting#create-checkout-session (`$details` is the array given to create a `Session`) | ||
|
||
## Subscription update payment details | ||
|
||
Same as the [previous chapter](#subscription-handling) | ||
|
||
Example : https://stripe.com/docs/payments/checkout/subscriptions/updating#create-checkout-session (`$details` is the array given to create a `Session`) | ||
- [Payment](payment.md) : How to process a Stripe Checkout Session payment ? | ||
- [Authorize](authorize.md) : How to place a hold on a card with Stripe Checkout Session ? | ||
- [Subscription](subscription.md) : How to handle subscription with Stripe Checkout Session ? | ||
- [Setup](setup.md) : How to set up future payments with Stripe Checkout Session ? | ||
|
||
## More | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Stripe Checkout Session : `payment` with `capture_method = manual` | ||
|
||
Authorize flow is following this Stripe doc page : | ||
https://stripe.com/docs/payments/capture-later | ||
|
||
## Get it started | ||
|
||
First get [your credentials](../stripe-credentials.md) from Stripe dashboard. | ||
|
||
> The following example is the basic Payum implementation | ||
> (see [documentation of Payum](https://github.com/Payum/Payum/blob/master/docs/get-it-started.md) for more information) | ||
Starting with the configuration of a normal payment, we will have to make some modification on the | ||
`prepare.php` file to generate an `AuthorizeToken`. Then we will trigger the `Authorize` request in an `authorize.php` file. | ||
|
||
### prepare.php | ||
|
||
```php | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
include __DIR__.'/config.php'; | ||
|
||
use Payum\Core\Model\Payment; | ||
|
||
$gatewayName = 'stripe_checkout_session'; | ||
|
||
$storage = $payum->getStorage(Payment::class); | ||
|
||
/** @var Payment $payment */ | ||
$payment = $storage->create(); | ||
$payment->setNumber(uniqid()); | ||
$payment->setCurrencyCode('EUR'); | ||
$payment->setTotalAmount(123); // 1.23 EUR | ||
$payment->setDescription('A description'); | ||
$payment->setClientId('anId'); | ||
$payment->setClientEmail('[email protected]'); | ||
$payment->setDetails([]); | ||
|
||
$storage->update($payment); | ||
|
||
$tokenFactory = $payum->getTokenFactory(); | ||
$captureToken = $tokenFactory->createAuthorizeToken($gatewayName, $payment, 'done.php'); | ||
|
||
header("Location: ".$captureToken->getTargetUrl()); | ||
``` | ||
|
||
### authorize.php | ||
|
||
```php | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
use Payum\Core\Reply\HttpResponse; | ||
use Payum\Core\Request\Authorize; | ||
use Payum\Core\Reply\HttpRedirect; | ||
|
||
include __DIR__.'/config.php'; | ||
|
||
$token = $payum->getHttpRequestVerifier()->verify($_REQUEST); | ||
$gateway = $payum->getGateway($token->getGatewayName()); | ||
|
||
if ($reply = $gateway->execute(new Authorize($token), true)) { | ||
if ($reply instanceof HttpRedirect) { | ||
header("Location: ".$reply->getUrl()); | ||
die(); | ||
} | ||
if ($reply instanceof HttpResponse) { | ||
echo $reply->getContent(); | ||
die(); | ||
} | ||
|
||
throw new \LogicException('Unsupported reply', null, $reply); | ||
} | ||
|
||
$payum->getHttpRequestVerifier()->invalidate($token); | ||
|
||
header("Location: ".$token->getAfterUrl()); | ||
``` | ||
|
||
## Finally, capture the authorized payment | ||
|
||
Complete the content of [`done.php`](payment.md#donephp) with those lines at the end of the file : | ||
|
||
```php | ||
if ($status->getValue() === $status::STATUS_AUTHORIZED) { | ||
$tokenFactory = $payum->getTokenFactory(); | ||
$token = $tokenFactory->createCaptureToken($gatewayName, $payment, 'done.php'); | ||
echo '<a href="'.$token->getTargetUrl().'">Capture</a>'; | ||
} | ||
``` | ||
|
||
|
||
|
Oops, something went wrong.