From 82c0e908984ab6007b935c700853117e39ffa440 Mon Sep 17 00:00:00 2001 From: andris-sevcenko Date: Tue, 9 Jul 2019 12:12:45 +0300 Subject: [PATCH] Add Payment Intents gateway. Add support for the SCA-ready Payment Intents API by adding a new gatewa. --- README.md | 3 +- src/AbstractGateway.php | 686 ++++++++++++++++++ src/Gateway.php | 631 +--------------- .../PaymentIntents/AbstractRequest.php | 62 ++ .../AttachPaymentMethodRequest.php | 68 ++ .../PaymentIntents/AuthorizeRequest.php | 374 ++++++++++ src/Message/PaymentIntents/CaptureRequest.php | 57 ++ .../ConfirmPaymentIntentRequest.php | 58 ++ .../CreatePaymentMethodRequest.php | 131 ++++ .../DetachPaymentMethodRequest.php | 60 ++ .../FetchPaymentIntentRequest.php | 57 ++ .../PaymentIntents/PurchaseRequest.php | 40 + src/Message/PaymentIntents/Response.php | 158 ++++ .../UpdatePaymentMethodRequest.php | 110 +++ src/Message/Response.php | 4 + src/PaymentIntentsGateway.php | 150 ++++ ...{GatewayTest.php => ChargeGatewayTest.php} | 2 +- .../PaymentIntents/AbstractRequestTest.php | 32 + .../AttachPaymentMethodRequestTest.php | 73 ++ .../PaymentIntents/AuthorizeRequestTest.php | 162 +++++ .../PaymentIntents/CaptureRequestTest.php | 54 ++ .../ConfirmPaymentIntentRequestTest.php | 72 ++ .../CreatePaymentMethodRequestTest.php | 112 +++ .../DetachPaymentMethodRequestTest.php | 59 ++ .../FetchPaymentIntentRequestTest.php | 63 ++ .../Mock/AttachPaymentMethodFailure.txt | 16 + .../Mock/AttachPaymentMethodSuccess.txt | 50 ++ .../PaymentIntents/Mock/AuthorizeFailure.txt | 24 + .../PaymentIntents/Mock/AuthorizeSuccess.txt | 60 ++ .../PaymentIntents/Mock/CaptureFailure.txt | 23 + .../PaymentIntents/Mock/CaptureSuccess.txt | 170 +++++ .../Mock/ConfirmIntent3dsRedirect.txt | 65 ++ .../Mock/ConfirmIntentMissingRedirect.txt | 65 ++ .../Mock/ConfirmIntentSuccess.txt | 150 ++++ .../Mock/CreatePaymentMethodFailure.txt | 19 + .../Mock/CreatePaymentMethodSuccess.txt | 50 ++ .../Mock/DetachPaymentMethodFailure.txt | 16 + .../Mock/DetachPaymentMethodSuccess.txt | 50 ++ .../Mock/FetchIntentFailure.txt | 24 + .../Mock/FetchIntentPaymentMethodRequired.txt | 105 +++ .../Mock/FetchIntentReadyToConfirm.txt | 59 ++ .../PaymentIntents/Mock/PurchaseSuccess.txt | 155 ++++ .../Mock/UpdatePaymentMethodFailure.txt | 16 + .../Mock/UpdatePaymentMethodSuccess.txt | 53 ++ .../PaymentIntents/PurchaseRequestTest.php | 60 ++ tests/Message/PaymentIntents/ResponseTest.php | 93 +++ .../UpdatePaymentMethodRequestTest.php | 62 ++ tests/PaymentIntentsGatewayTest.php | 296 ++++++++ 48 files changed, 4339 insertions(+), 620 deletions(-) create mode 100644 src/AbstractGateway.php create mode 100644 src/Message/PaymentIntents/AbstractRequest.php create mode 100644 src/Message/PaymentIntents/AttachPaymentMethodRequest.php create mode 100644 src/Message/PaymentIntents/AuthorizeRequest.php create mode 100644 src/Message/PaymentIntents/CaptureRequest.php create mode 100644 src/Message/PaymentIntents/ConfirmPaymentIntentRequest.php create mode 100644 src/Message/PaymentIntents/CreatePaymentMethodRequest.php create mode 100644 src/Message/PaymentIntents/DetachPaymentMethodRequest.php create mode 100644 src/Message/PaymentIntents/FetchPaymentIntentRequest.php create mode 100644 src/Message/PaymentIntents/PurchaseRequest.php create mode 100644 src/Message/PaymentIntents/Response.php create mode 100644 src/Message/PaymentIntents/UpdatePaymentMethodRequest.php create mode 100644 src/PaymentIntentsGateway.php rename tests/{GatewayTest.php => ChargeGatewayTest.php} (99%) create mode 100644 tests/Message/PaymentIntents/AbstractRequestTest.php create mode 100644 tests/Message/PaymentIntents/AttachPaymentMethodRequestTest.php create mode 100644 tests/Message/PaymentIntents/AuthorizeRequestTest.php create mode 100644 tests/Message/PaymentIntents/CaptureRequestTest.php create mode 100644 tests/Message/PaymentIntents/ConfirmPaymentIntentRequestTest.php create mode 100644 tests/Message/PaymentIntents/CreatePaymentMethodRequestTest.php create mode 100644 tests/Message/PaymentIntents/DetachPaymentMethodRequestTest.php create mode 100644 tests/Message/PaymentIntents/FetchPaymentIntentRequestTest.php create mode 100644 tests/Message/PaymentIntents/Mock/AttachPaymentMethodFailure.txt create mode 100644 tests/Message/PaymentIntents/Mock/AttachPaymentMethodSuccess.txt create mode 100644 tests/Message/PaymentIntents/Mock/AuthorizeFailure.txt create mode 100644 tests/Message/PaymentIntents/Mock/AuthorizeSuccess.txt create mode 100644 tests/Message/PaymentIntents/Mock/CaptureFailure.txt create mode 100644 tests/Message/PaymentIntents/Mock/CaptureSuccess.txt create mode 100644 tests/Message/PaymentIntents/Mock/ConfirmIntent3dsRedirect.txt create mode 100644 tests/Message/PaymentIntents/Mock/ConfirmIntentMissingRedirect.txt create mode 100644 tests/Message/PaymentIntents/Mock/ConfirmIntentSuccess.txt create mode 100644 tests/Message/PaymentIntents/Mock/CreatePaymentMethodFailure.txt create mode 100644 tests/Message/PaymentIntents/Mock/CreatePaymentMethodSuccess.txt create mode 100644 tests/Message/PaymentIntents/Mock/DetachPaymentMethodFailure.txt create mode 100644 tests/Message/PaymentIntents/Mock/DetachPaymentMethodSuccess.txt create mode 100644 tests/Message/PaymentIntents/Mock/FetchIntentFailure.txt create mode 100644 tests/Message/PaymentIntents/Mock/FetchIntentPaymentMethodRequired.txt create mode 100644 tests/Message/PaymentIntents/Mock/FetchIntentReadyToConfirm.txt create mode 100644 tests/Message/PaymentIntents/Mock/PurchaseSuccess.txt create mode 100644 tests/Message/PaymentIntents/Mock/UpdatePaymentMethodFailure.txt create mode 100644 tests/Message/PaymentIntents/Mock/UpdatePaymentMethodSuccess.txt create mode 100644 tests/Message/PaymentIntents/PurchaseRequestTest.php create mode 100644 tests/Message/PaymentIntents/ResponseTest.php create mode 100644 tests/Message/PaymentIntents/UpdatePaymentMethodRequestTest.php create mode 100644 tests/PaymentIntentsGatewayTest.php diff --git a/README.md b/README.md index fda6e682..c5b491df 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,8 @@ composer require league/omnipay omnipay/stripe The following gateways are provided by this package: -* [Stripe](https://stripe.com/) +* [Stripe Charge](https://stripe.com/docs/charges) +* [Stripe Payment Intents](https://stripe.com/docs/payments/payment-intents) For general usage instructions, please see the main [Omnipay](https://github.com/thephpleague/omnipay) repository. diff --git a/src/AbstractGateway.php b/src/AbstractGateway.php new file mode 100644 index 00000000..91808800 --- /dev/null +++ b/src/AbstractGateway.php @@ -0,0 +1,686 @@ + + * // Create a gateway for the Stripe Gateway + * // (routes to GatewayFactory::create) + * $gateway = Omnipay::create('Stripe'); + * + * // Initialise the gateway + * $gateway->initialize(array( + * 'apiKey' => 'MyApiKey', + * )); + * + * // Create a credit card object + * // This card can be used for testing. + * $card = new CreditCard(array( + * 'firstName' => 'Example', + * 'lastName' => 'Customer', + * 'number' => '4242424242424242', + * 'expiryMonth' => '01', + * 'expiryYear' => '2020', + * 'cvv' => '123', + * 'email' => 'customer@example.com', + * 'billingAddress1' => '1 Scrubby Creek Road', + * 'billingCountry' => 'AU', + * 'billingCity' => 'Scrubby Creek', + * 'billingPostcode' => '4999', + * 'billingState' => 'QLD', + * )); + * + * // Do a purchase transaction on the gateway + * $transaction = $gateway->purchase(array( + * 'amount' => '10.00', + * 'currency' => 'USD', + * 'card' => $card, + * )); + * $response = $transaction->send(); + * if ($response->isSuccessful()) { + * echo "Purchase transaction was successful!\n"; + * $sale_id = $response->getTransactionReference(); + * echo "Transaction reference = " . $sale_id . "\n"; + * + * $balance_transaction_id = $response->getBalanceTransactionReference(); + * echo "Balance Transaction reference = " . $balance_transaction_id . "\n"; + * } + * + * + * Test modes: + * + * Stripe accounts have test-mode API keys as well as live-mode + * API keys. These keys can be active at the same time. Data + * created with test-mode credentials will never hit the credit + * card networks and will never cost anyone money. + * + * Unlike some gateways, there is no test mode endpoint separate + * to the live mode endpoint, the Stripe API endpoint is the same + * for test and for live. + * + * Setting the testMode flag on this gateway has no effect. To + * use test mode just use your test mode API key. + * + * You can use any of the cards listed at https://stripe.com/docs/testing + * for testing. + * + * Authentication: + * + * Authentication is by means of a single secret API key set as + * the apiKey parameter when creating the gateway object. + * + * @see \Omnipay\Common\AbstractGateway + * @see \Omnipay\Stripe\Message\AbstractRequest + * + * @link https://stripe.com/docs/api + * + * @method \Omnipay\Common\Message\RequestInterface completeAuthorize(array $options = array()) + * @method \Omnipay\Common\Message\RequestInterface completePurchase(array $options = array()) + */ +abstract class AbstractGateway extends AbstractOmnipayGateway +{ + const BILLING_PLAN_FREQUENCY_DAY = 'day'; + const BILLING_PLAN_FREQUENCY_WEEK = 'week'; + const BILLING_PLAN_FREQUENCY_MONTH = 'month'; + const BILLING_PLAN_FREQUENCY_YEAR = 'year'; + + /** + * @inheritdoc + */ + abstract public function getName(); + + /** + * Get the gateway parameters. + * + * @return array + */ + public function getDefaultParameters() + { + return array( + 'apiKey' => '', + ); + } + + /** + * Get the gateway API Key. + * + * Authentication is by means of a single secret API key set as + * the apiKey parameter when creating the gateway object. + * + * @return string + */ + public function getApiKey() + { + return $this->getParameter('apiKey'); + } + + /** + * Set the gateway API Key. + * + * Authentication is by means of a single secret API key set as + * the apiKey parameter when creating the gateway object. + * + * Stripe accounts have test-mode API keys as well as live-mode + * API keys. These keys can be active at the same time. Data + * created with test-mode credentials will never hit the credit + * card networks and will never cost anyone money. + * + * Unlike some gateways, there is no test mode endpoint separate + * to the live mode endpoint, the Stripe API endpoint is the same + * for test and for live. + * + * Setting the testMode flag on this gateway has no effect. To + * use test mode just use your test mode API key. + * + * @param string $value + * + * @return Gateway provides a fluent interface. + */ + public function setApiKey($value) + { + return $this->setParameter('apiKey', $value); + } + + /** + * Authorize Request. + * + * An Authorize request is similar to a purchase request but the + * charge issues an authorization (or pre-authorization), and no money + * is transferred. The transaction will need to be captured later + * in order to effect payment. Uncaptured charges expire in 7 days. + * + * Either a customerReference or a card is required. If a customerReference + * is passed in then the cardReference must be the reference of a card + * assigned to the customer. Otherwise, if you do not pass a customer ID, + * the card you provide must either be a token, like the ones returned by + * Stripe.js, or a dictionary containing a user's credit card details. + * + * IN OTHER WORDS: You cannot just pass a card reference into this request, + * you must also provide a customer reference if you want to use a stored + * card. + * + * @param array $parameters + * + * @return \Omnipay\Stripe\Message\AbstractRequest + */ + abstract public function authorize(array $parameters = array()); + + /** + * Capture Request. + * + * Use this request to capture and process a previously created authorization. + * + * @param array $parameters + * + * @return \Omnipay\Stripe\Message\AbstractRequest + */ + abstract public function capture(array $parameters = array()); + + /** + * Purchase request. + * + * To charge a credit card, you create a new charge object. If your API key + * is in test mode, the supplied card won't actually be charged, though + * everything else will occur as if in live mode. (Stripe assumes that the + * charge would have completed successfully). + * + * Either a customerReference or a card is required. If a customerReference + * is passed in then the cardReference must be the reference of a card + * assigned to the customer. Otherwise, if you do not pass a customer ID, + * the card you provide must either be a token, like the ones returned by + * Stripe.js, or a dictionary containing a user's credit card details. + * + * IN OTHER WORDS: You cannot just pass a card reference into this request, + * you must also provide a customer reference if you want to use a stored + * card. + * + * @param array $parameters + * + * @return \Omnipay\Stripe\Message\AbstractRequest + */ + abstract public function purchase(array $parameters = array()); + + /** + * Refund Request. + * + * When you create a new refund, you must specify a + * charge to create it on. + * + * Creating a new refund will refund a charge that has + * previously been created but not yet refunded. Funds will + * be refunded to the credit or debit card that was originally + * charged. The fees you were originally charged are also + * refunded. + * + * @param array $parameters + * + * @return \Omnipay\Stripe\Message\RefundRequest + */ + public function refund(array $parameters = []) + { + return $this->createRequest('\Omnipay\Stripe\Message\RefundRequest', $parameters); + } + + /** + * Void a transaction. + * + * @param array $parameters + * + * @return \Omnipay\Stripe\Message\VoidRequest + */ + public function void(array $parameters = []) + { + return $this->createRequest('\Omnipay\Stripe\Message\VoidRequest', $parameters); + } + + /** + * Fetch a transaction. + * + * @param array $parameters + * + * @return \Omnipay\Stripe\Message\FetchTransactionRequest + */ + public function fetchTransaction(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\FetchTransactionRequest', $parameters); + } + + /** + * @param array $parameters + * @return \Omnipay\Stripe\Message\FetchBalanceTransactionRequest + */ + public function fetchBalanceTransaction(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\FetchBalanceTransactionRequest', $parameters); + } + + // + // Transfers + // @link https://stripe.com/docs/api#transfers + // + + /** + * Transfer Request. + * + * To send funds from your Stripe account to a connected account, you create + * a new transfer object. Your Stripe balance must be able to cover the + * transfer amount, or you'll receive an "Insufficient Funds" error. + * + * @param array $parameters + * + * @return \Omnipay\Common\Message\AbstractRequest + */ + public function transfer(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\Transfers\CreateTransferRequest', $parameters); + } + + /** + * @param array $parameters + * + * @return \Omnipay\Common\Message\AbstractRequest + */ + public function fetchTransfer(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\Transfers\FetchTransferRequest', $parameters); + } + + /** + * @param array $parameters + * + * @return \Omnipay\Common\Message\AbstractRequest + */ + public function updateTransfer(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\Transfers\UpdateTransferRequest', $parameters); + } + + /** + * List Transfers + * + * @param array $parameters + * + * @return \Omnipay\Common\Message\AbstractRequest|\Omnipay\Stripe\Message\Transfers\ListTransfersRequest + */ + public function listTransfers(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\Transfers\ListTransfersRequest', $parameters); + } + + /** + * @param array $parameters + * + * @return \Omnipay\Common\Message\AbstractRequest + */ + public function reverseTransfer(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\Transfers\CreateTransferReversalRequest', $parameters); + } + + /** + * @param array $parameters + * + * @return \Omnipay\Common\Message\AbstractRequest + */ + public function fetchTransferReversal(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\Transfers\FetchTransferReversalRequest', $parameters); + } + + /** + * @param array $parameters + * + * @return \Omnipay\Common\Message\AbstractRequest + */ + public function updateTransferReversal(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\Transfers\UpdateTransferReversalRequest', $parameters); + } + + /** + * @param array $parameters + * + * @return \Omnipay\Common\Message\AbstractRequest + */ + public function listTransferReversals(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\Transfers\ListTransferReversalsRequest', $parameters); + } + + // + // Cards + // @link https://stripe.com/docs/api#cards + // + + /** + * Create Card. + * + * This call can be used to create a new customer or add a card + * to an existing customer. If a customerReference is passed in then + * a card is added to an existing customer. If there is no + * customerReference passed in then a new customer is created. The + * response in that case will then contain both a customer token + * and a card token, and is essentially the same as CreateCustomerRequest + * + * @param array $parameters + * + * @return \Omnipay\Stripe\Message\AbstractRequest + */ + public function createCard(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\CreateCardRequest', $parameters); + } + + /** + * Update Card. + * + * If you need to update only some card details, like the billing + * address or expiration date, you can do so without having to re-enter + * the full card details. Stripe also works directly with card networks + * so that your customers can continue using your service without + * interruption. + * + * When you update a card, Stripe will automatically validate the card. + * + * This requires both a customerReference and a cardReference. + * + * @link https://stripe.com/docs/api#update_card + * + * @param array $parameters + * + * @return \Omnipay\Stripe\Message\AbstractRequest + */ + public function updateCard(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\UpdateCardRequest', $parameters); + } + + /** + * Delete a card. + * + * This is normally used to delete a credit card from an existing + * customer. + * + * You can delete cards from a customer or recipient. If you delete a + * card that is currently the default card on a customer or recipient, + * the most recently added card will be used as the new default. If you + * delete the last remaining card on a customer or recipient, the + * default_card attribute on the card's owner will become null. + * + * Note that for cards belonging to customers, you may want to prevent + * customers on paid subscriptions from deleting all cards on file so + * that there is at least one default card for the next invoice payment + * attempt. + * + * In deference to the previous incarnation of this gateway, where + * all CreateCard requests added a new customer and the customer ID + * was used as the card ID, if a cardReference is passed in but no + * customerReference then we assume that the cardReference is in fact + * a customerReference and delete the customer. This might be + * dangerous but it's the best way to ensure backwards compatibility. + * + * @param array $parameters + * + * @return \Omnipay\Stripe\Message\AbstractRequest + */ + public function deleteCard(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\DeleteCardRequest', $parameters); + } + + // + // Customers + // link: https://stripe.com/docs/api#customers + // + + /** + * Create Customer. + * + * Customer objects allow you to perform recurring charges and + * track multiple charges that are associated with the same customer. + * The API allows you to create, delete, and update your customers. + * You can retrieve individual customers as well as a list of all of + * your customers. + * + * @param array $parameters + * + * @return \Omnipay\Stripe\Message\CreateCustomerRequest + */ + public function createCustomer(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\CreateCustomerRequest', $parameters); + } + + /** + * Fetch Customer. + * + * Fetches customer by customer reference. + * + * @param array $parameters + * + * @return \Omnipay\Stripe\Message\FetchCustomerRequest + */ + public function fetchCustomer(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\FetchCustomerRequest', $parameters); + } + + /** + * Update Customer. + * + * This request updates the specified customer by setting the values + * of the parameters passed. Any parameters not provided will be left + * unchanged. For example, if you pass the card parameter, that becomes + * the customer's active card to be used for all charges in the future, + * and the customer email address is updated to the email address + * on the card. When you update a customer to a new valid card: for + * each of the customer's current subscriptions, if the subscription + * is in the `past_due` state, then the latest unpaid, unclosed + * invoice for the subscription will be retried (note that this retry + * will not count as an automatic retry, and will not affect the next + * regularly scheduled payment for the invoice). (Note also that no + * invoices pertaining to subscriptions in the `unpaid` state, or + * invoices pertaining to canceled subscriptions, will be retried as + * a result of updating the customer's card.) + * + * This request accepts mostly the same arguments as the customer + * creation call. + * + * @param array $parameters + * + * @return \Omnipay\Stripe\Message\CreateCustomerRequest + */ + public function updateCustomer(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\UpdateCustomerRequest', $parameters); + } + + /** + * Delete a customer. + * + * Permanently deletes a customer. It cannot be undone. Also immediately + * cancels any active subscriptions on the customer. + * + * @param array $parameters + * + * @return \Omnipay\Stripe\Message\DeleteCustomerRequest + */ + public function deleteCustomer(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\DeleteCustomerRequest', $parameters); + } + + /** + * Create Plan + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\CreatePlanRequest + */ + public function createPlan(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\CreatePlanRequest', $parameters); + } + + /** + * Fetch Plan + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\FetchPlanRequest + */ + public function fetchPlan(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\FetchPlanRequest', $parameters); + } + + /** + * Delete Plan + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\DeletePlanRequest + */ + public function deletePlan(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\DeletePlanRequest', $parameters); + } + + /** + * List Plans + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\ListPlansRequest + */ + public function listPlans(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\ListPlansRequest', $parameters); + } + + /** + * Create Subscription + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\CreateSubscriptionRequest + */ + public function createSubscription(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\CreateSubscriptionRequest', $parameters); + } + + /** + * Fetch Subscription + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\FetchSubscriptionRequest + */ + public function fetchSubscription(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\FetchSubscriptionRequest', $parameters); + } + + /** + * Update Subscription + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\UpdateSubscriptionRequest + */ + public function updateSubscription(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\UpdateSubscriptionRequest', $parameters); + } + + /** + * Cancel Subscription + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\CancelSubscriptionRequest + */ + public function cancelSubscription(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\CancelSubscriptionRequest', $parameters); + } + + /** + * Fetch Event + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\FetchEventRequest + */ + public function fetchEvent(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\FetchEventRequest', $parameters); + } + + /** + * Fetch Invoice Lines + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\FetchInvoiceLinesRequest + */ + public function fetchInvoiceLines(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\FetchInvoiceLinesRequest', $parameters); + } + + /** + * Fetch Invoice + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\FetchInvoiceRequest + */ + public function fetchInvoice(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\FetchInvoiceRequest', $parameters); + } + + /** + * List Invoices + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\ListInvoicesRequest + */ + public function listInvoices(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\ListInvoicesRequest', $parameters); + } + + /** + * Create Invoice Item + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\CreateInvoiceItemRequest + */ + public function createInvoiceItem(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\CreateInvoiceItemRequest', $parameters); + } + + /** + * Fetch Invoice Item + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\FetchInvoiceItemRequest + */ + public function fetchInvoiceItem(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\FetchInvoiceItemRequest', $parameters); + } + + /** + * Delete Invoice Item + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\DeleteInvoiceItemRequest + */ + public function deleteInvoiceItem(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\DeleteInvoiceItemRequest', $parameters); + } +} diff --git a/src/Gateway.php b/src/Gateway.php index b0532e55..d7a8becd 100644 --- a/src/Gateway.php +++ b/src/Gateway.php @@ -1,175 +1,31 @@ - * // Create a gateway for the Stripe Gateway - * // (routes to GatewayFactory::create) - * $gateway = Omnipay::create('Stripe'); - * - * // Initialise the gateway - * $gateway->initialize(array( - * 'apiKey' => 'MyApiKey', - * )); - * - * // Create a credit card object - * // This card can be used for testing. - * $card = new CreditCard(array( - * 'firstName' => 'Example', - * 'lastName' => 'Customer', - * 'number' => '4242424242424242', - * 'expiryMonth' => '01', - * 'expiryYear' => '2020', - * 'cvv' => '123', - * 'email' => 'customer@example.com', - * 'billingAddress1' => '1 Scrubby Creek Road', - * 'billingCountry' => 'AU', - * 'billingCity' => 'Scrubby Creek', - * 'billingPostcode' => '4999', - * 'billingState' => 'QLD', - * )); - * - * // Do a purchase transaction on the gateway - * $transaction = $gateway->purchase(array( - * 'amount' => '10.00', - * 'currency' => 'USD', - * 'card' => $card, - * )); - * $response = $transaction->send(); - * if ($response->isSuccessful()) { - * echo "Purchase transaction was successful!\n"; - * $sale_id = $response->getTransactionReference(); - * echo "Transaction reference = " . $sale_id . "\n"; - * - * $balance_transaction_id = $response->getBalanceTransactionReference(); - * echo "Balance Transaction reference = " . $balance_transaction_id . "\n"; - * } - * - * - * Test modes: - * - * Stripe accounts have test-mode API keys as well as live-mode - * API keys. These keys can be active at the same time. Data - * created with test-mode credentials will never hit the credit - * card networks and will never cost anyone money. - * - * Unlike some gateways, there is no test mode endpoint separate - * to the live mode endpoint, the Stripe API endpoint is the same - * for test and for live. + * Stripe Charge Gateway. * - * Setting the testMode flag on this gateway has no effect. To - * use test mode just use your test mode API key. - * - * You can use any of the cards listed at https://stripe.com/docs/testing - * for testing. - * - * Authentication: - * - * Authentication is by means of a single secret API key set as - * the apiKey parameter when creating the gateway object. - * - * @see \Omnipay\Common\AbstractGateway + * @see \Omnipay\Stripe\AbstractGateway * @see \Omnipay\Stripe\Message\AbstractRequest * * @link https://stripe.com/docs/api * - * @method \Omnipay\Common\Message\RequestInterface completeAuthorize(array $options = array()) - * @method \Omnipay\Common\Message\RequestInterface completePurchase(array $options = array()) */ class Gateway extends AbstractGateway { - const BILLING_PLAN_FREQUENCY_DAY = 'day'; - const BILLING_PLAN_FREQUENCY_WEEK = 'week'; - const BILLING_PLAN_FREQUENCY_MONTH = 'month'; - const BILLING_PLAN_FREQUENCY_YEAR = 'year'; - - public function getName() - { - return 'Stripe'; - } - /** - * Get the gateway parameters. - * - * @return array + * @inheritdoc */ - public function getDefaultParameters() - { - return array( - 'apiKey' => '', - ); - } - - /** - * Get the gateway API Key. - * - * Authentication is by means of a single secret API key set as - * the apiKey parameter when creating the gateway object. - * - * @return string - */ - public function getApiKey() - { - return $this->getParameter('apiKey'); - } - - /** - * Set the gateway API Key. - * - * Authentication is by means of a single secret API key set as - * the apiKey parameter when creating the gateway object. - * - * Stripe accounts have test-mode API keys as well as live-mode - * API keys. These keys can be active at the same time. Data - * created with test-mode credentials will never hit the credit - * card networks and will never cost anyone money. - * - * Unlike some gateways, there is no test mode endpoint separate - * to the live mode endpoint, the Stripe API endpoint is the same - * for test and for live. - * - * Setting the testMode flag on this gateway has no effect. To - * use test mode just use your test mode API key. - * - * @param string $value - * - * @return Gateway provides a fluent interface. - */ - public function setApiKey($value) + public function getName() { - return $this->setParameter('apiKey', $value); + return 'Stripe Charge'; } /** - * Authorize Request. - * - * An Authorize request is similar to a purchase request but the - * charge issues an authorization (or pre-authorization), and no money - * is transferred. The transaction will need to be captured later - * in order to effect payment. Uncaptured charges expire in 7 days. - * - * Either a customerReference or a card is required. If a customerReference - * is passed in then the cardReference must be the reference of a card - * assigned to the customer. Otherwise, if you do not pass a customer ID, - * the card you provide must either be a token, like the ones returned by - * Stripe.js, or a dictionary containing a user's credit card details. - * - * IN OTHER WORDS: You cannot just pass a card reference into this request, - * you must also provide a customer reference if you want to use a stored - * card. - * - * @param array $parameters + * @inheritdoc * * @return \Omnipay\Stripe\Message\AuthorizeRequest */ @@ -179,11 +35,7 @@ public function authorize(array $parameters = array()) } /** - * Capture Request. - * - * Use this request to capture and process a previously created authorization. - * - * @param array $parameters + * @inheritdoc * * @return \Omnipay\Stripe\Message\CaptureRequest */ @@ -193,24 +45,7 @@ public function capture(array $parameters = array()) } /** - * Purchase request. - * - * To charge a credit card, you create a new charge object. If your API key - * is in test mode, the supplied card won't actually be charged, though - * everything else will occur as if in live mode. (Stripe assumes that the - * charge would have completed successfully). - * - * Either a customerReference or a card is required. If a customerReference - * is passed in then the cardReference must be the reference of a card - * assigned to the customer. Otherwise, if you do not pass a customer ID, - * the card you provide must either be a token, like the ones returned by - * Stripe.js, or a dictionary containing a user's credit card details. - * - * IN OTHER WORDS: You cannot just pass a card reference into this request, - * you must also provide a customer reference if you want to use a stored - * card. - * - * @param array $parameters + * @inheritdoc * * @return \Omnipay\Stripe\Message\PurchaseRequest */ @@ -219,39 +54,6 @@ public function purchase(array $parameters = array()) return $this->createRequest('\Omnipay\Stripe\Message\PurchaseRequest', $parameters); } - /** - * Refund Request. - * - * When you create a new refund, you must specify a - * charge to create it on. - * - * Creating a new refund will refund a charge that has - * previously been created but not yet refunded. Funds will - * be refunded to the credit or debit card that was originally - * charged. The fees you were originally charged are also - * refunded. - * - * @param array $parameters - * - * @return \Omnipay\Stripe\Message\RefundRequest - */ - public function refund(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\RefundRequest', $parameters); - } - - /** - * Fetch Transaction Request. - * - * @param array $parameters - * - * @return \Omnipay\Stripe\Message\VoidRequest - */ - public function void(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\VoidRequest', $parameters); - } - /** * @deprecated 2.3.3:3.0.0 duplicate of \Omnipay\Stripe\Gateway::fetchTransaction() * @see \Omnipay\Stripe\Gateway::fetchTransaction() @@ -263,136 +65,13 @@ public function fetchCharge(array $parameters = array()) return $this->createRequest('\Omnipay\Stripe\Message\FetchChargeRequest', $parameters); } - /** - * @param array $parameters - * - * @return \Omnipay\Stripe\Message\FetchTransactionRequest - */ - public function fetchTransaction(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\FetchTransactionRequest', $parameters); - } - - /** - * @param array $parameters - * @return \Omnipay\Stripe\Message\FetchBalanceTransactionRequest - */ - public function fetchBalanceTransaction(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\FetchBalanceTransactionRequest', $parameters); - } - - - // - // Transfers - // @link https://stripe.com/docs/api#transfers - // - - - /** - * Transfer Request. - * - * To send funds from your Stripe account to a connected account, you create - * a new transfer object. Your Stripe balance must be able to cover the - * transfer amount, or you'll receive an "Insufficient Funds" error. - * - * @param array $parameters - * - * @return \Omnipay\Common\Message\AbstractRequest - */ - public function transfer(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\Transfers\CreateTransferRequest', $parameters); - } - - /** - * @param array $parameters - * - * @return \Omnipay\Common\Message\AbstractRequest - */ - public function fetchTransfer(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\Transfers\FetchTransferRequest', $parameters); - } - - /** - * @param array $parameters - * - * @return \Omnipay\Common\Message\AbstractRequest - */ - public function updateTransfer(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\Transfers\UpdateTransferRequest', $parameters); - } - - /** - * List Transfers - * - * @param array $parameters - * - * @return \Omnipay\Common\Message\AbstractRequest|\Omnipay\Stripe\Message\Transfers\ListTransfersRequest - */ - public function listTransfers(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\Transfers\ListTransfersRequest', $parameters); - } - - /** - * @param array $parameters - * - * @return \Omnipay\Common\Message\AbstractRequest - */ - public function reverseTransfer(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\Transfers\CreateTransferReversalRequest', $parameters); - } - - /** - * @param array $parameters - * - * @return \Omnipay\Common\Message\AbstractRequest - */ - public function fetchTransferReversal(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\Transfers\FetchTransferReversalRequest', $parameters); - } - - /** - * @param array $parameters - * - * @return \Omnipay\Common\Message\AbstractRequest - */ - public function updateTransferReversal(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\Transfers\UpdateTransferReversalRequest', $parameters); - } - - /** - * @param array $parameters - * - * @return \Omnipay\Common\Message\AbstractRequest - */ - public function listTransferReversals(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\Transfers\ListTransferReversalsRequest', $parameters); - } - // // Cards // @link https://stripe.com/docs/api#cards // /** - * Create Card. - * - * This call can be used to create a new customer or add a card - * to an existing customer. If a customerReference is passed in then - * a card is added to an existing customer. If there is no - * customerReference passed in then a new customer is created. The - * response in that case will then contain both a customer token - * and a card token, and is essentially the same as CreateCustomerRequest - * - * @param array $parameters + * @inheritdoc * * @return \Omnipay\Stripe\Message\CreateCardRequest */ @@ -402,21 +81,7 @@ public function createCard(array $parameters = array()) } /** - * Update Card. - * - * If you need to update only some card details, like the billing - * address or expiration date, you can do so without having to re-enter - * the full card details. Stripe also works directly with card networks - * so that your customers can continue using your service without - * interruption. - * - * When you update a card, Stripe will automatically validate the card. - * - * This requires both a customerReference and a cardReference. - * - * @link https://stripe.com/docs/api#update_card - * - * @param array $parameters + * @inheritdoc * * @return \Omnipay\Stripe\Message\UpdateCardRequest */ @@ -426,30 +91,7 @@ public function updateCard(array $parameters = array()) } /** - * Delete a card. - * - * This is normally used to delete a credit card from an existing - * customer. - * - * You can delete cards from a customer or recipient. If you delete a - * card that is currently the default card on a customer or recipient, - * the most recently added card will be used as the new default. If you - * delete the last remaining card on a customer or recipient, the - * default_card attribute on the card's owner will become null. - * - * Note that for cards belonging to customers, you may want to prevent - * customers on paid subscriptions from deleting all cards on file so - * that there is at least one default card for the next invoice payment - * attempt. - * - * In deference to the previous incarnation of this gateway, where - * all CreateCard requests added a new customer and the customer ID - * was used as the card ID, if a cardReference is passed in but no - * customerReference then we assume that the cardReference is in fact - * a customerReference and delete the customer. This might be - * dangerous but it's the best way to ensure backwards compatibility. - * - * @param array $parameters + * @inheritdoc * * @return \Omnipay\Stripe\Message\DeleteCardRequest */ @@ -458,88 +100,6 @@ public function deleteCard(array $parameters = array()) return $this->createRequest('\Omnipay\Stripe\Message\DeleteCardRequest', $parameters); } - // - // Customers - // link: https://stripe.com/docs/api#customers - // - - /** - * Create Customer. - * - * Customer objects allow you to perform recurring charges and - * track multiple charges that are associated with the same customer. - * The API allows you to create, delete, and update your customers. - * You can retrieve individual customers as well as a list of all of - * your customers. - * - * @param array $parameters - * - * @return \Omnipay\Stripe\Message\CreateCustomerRequest - */ - public function createCustomer(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\CreateCustomerRequest', $parameters); - } - - /** - * Fetch Customer. - * - * Fetches customer by customer reference. - * - * @param array $parameters - * - * @return \Omnipay\Stripe\Message\FetchCustomerRequest - */ - public function fetchCustomer(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\FetchCustomerRequest', $parameters); - } - - /** - * Update Customer. - * - * This request updates the specified customer by setting the values - * of the parameters passed. Any parameters not provided will be left - * unchanged. For example, if you pass the card parameter, that becomes - * the customer's active card to be used for all charges in the future, - * and the customer email address is updated to the email address - * on the card. When you update a customer to a new valid card: for - * each of the customer's current subscriptions, if the subscription - * is in the `past_due` state, then the latest unpaid, unclosed - * invoice for the subscription will be retried (note that this retry - * will not count as an automatic retry, and will not affect the next - * regularly scheduled payment for the invoice). (Note also that no - * invoices pertaining to subscriptions in the `unpaid` state, or - * invoices pertaining to canceled subscriptions, will be retried as - * a result of updating the customer's card.) - * - * This request accepts mostly the same arguments as the customer - * creation call. - * - * @param array $parameters - * - * @return \Omnipay\Stripe\Message\CreateCustomerRequest - */ - public function updateCustomer(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\UpdateCustomerRequest', $parameters); - } - - /** - * Delete a customer. - * - * Permanently deletes a customer. It cannot be undone. Also immediately - * cancels any active subscriptions on the customer. - * - * @param array $parameters - * - * @return \Omnipay\Stripe\Message\DeleteCustomerRequest - */ - public function deleteCustomer(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\DeleteCustomerRequest', $parameters); - } - // // Tokens // @link https://stripe.com/docs/api#tokens @@ -554,7 +114,7 @@ public function deleteCustomer(array $parameters = array()) * Use this request to create a new token to make a direct charge on a customer of the platform. * * @param array $parameters parameters to be passed in to the TokenRequest. - * @return CreateTokenRequest|\Omnipay\Common\Message\AbstractRequest The create token request. + * @return \Omnipay\Stripe\Message\CreateTokenRequest The create token request. */ public function createToken(array $parameters = array()) { @@ -584,169 +144,4 @@ public function fetchToken(array $parameters = array()) { return $this->createRequest('\Omnipay\Stripe\Message\FetchTokenRequest', $parameters); } - - /** - * Create Plan - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\CreatePlanRequest - */ - public function createPlan(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\CreatePlanRequest', $parameters); - } - - /** - * Fetch Plan - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\FetchPlanRequest - */ - public function fetchPlan(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\FetchPlanRequest', $parameters); - } - - /** - * Delete Plan - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\DeletePlanRequest - */ - public function deletePlan(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\DeletePlanRequest', $parameters); - } - - /** - * List Plans - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\ListPlansRequest - */ - public function listPlans(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\ListPlansRequest', $parameters); - } - - /** - * Create Subscription - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\CreateSubscriptionRequest - */ - public function createSubscription(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\CreateSubscriptionRequest', $parameters); - } - - /** - * Fetch Subscription - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\FetchSubscriptionRequest - */ - public function fetchSubscription(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\FetchSubscriptionRequest', $parameters); - } - - /** - * Update Subscription - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\UpdateSubscriptionRequest - */ - public function updateSubscription(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\UpdateSubscriptionRequest', $parameters); - } - - /** - * Cancel Subscription - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\CancelSubscriptionRequest - */ - public function cancelSubscription(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\CancelSubscriptionRequest', $parameters); - } - - /** - * Fetch Event - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\FetchEventRequest - */ - public function fetchEvent(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\FetchEventRequest', $parameters); - } - - /** - * Fetch Invoice Lines - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\FetchInvoiceLinesRequest - */ - public function fetchInvoiceLines(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\FetchInvoiceLinesRequest', $parameters); - } - - /** - * Fetch Invoice - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\FetchInvoiceRequest - */ - public function fetchInvoice(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\FetchInvoiceRequest', $parameters); - } - - /** - * List Invoices - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\ListInvoicesRequest - */ - public function listInvoices(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\ListInvoicesRequest', $parameters); - } - - /** - * Create Invoice Item - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\CreateInvoiceItemRequest - */ - public function createInvoiceItem(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\CreateInvoiceItemRequest', $parameters); - } - - /** - * Fetch Invoice Item - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\FetchInvoiceItemRequest - */ - public function fetchInvoiceItem(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\FetchInvoiceItemRequest', $parameters); - } - - /** - * Delete Invoice Item - * - * @param array $parameters - * @return \Omnipay\Stripe\Message\DeleteInvoiceItemRequest - */ - public function deleteInvoiceItem(array $parameters = array()) - { - return $this->createRequest('\Omnipay\Stripe\Message\DeleteInvoiceItemRequest', $parameters); - } } diff --git a/src/Message/PaymentIntents/AbstractRequest.php b/src/Message/PaymentIntents/AbstractRequest.php new file mode 100644 index 00000000..9a62e6bc --- /dev/null +++ b/src/Message/PaymentIntents/AbstractRequest.php @@ -0,0 +1,62 @@ +setParameter('paymentIntentReference', $value); + } + + /** + * @return mixed + */ + public function getPaymentIntentReference() + { + return $this->getParameter('paymentIntentReference'); + } + + /** + * If there's a reference to a payment method, return that instead. + * + * @inheritdoc + */ + public function getCardReference() + { + if ($paymentMethod = $this->getPaymentMethod()) { + return $paymentMethod; + } + + return parent::getCardReference(); + } + + /** + * Actually, set the payment method, which is the preferred API. + * + * @inheritdoc + */ + public function setCardReference($reference) + { + $this->setPaymentMethod($reference); + } +} diff --git a/src/Message/PaymentIntents/AttachPaymentMethodRequest.php b/src/Message/PaymentIntents/AttachPaymentMethodRequest.php new file mode 100644 index 00000000..a28266e2 --- /dev/null +++ b/src/Message/PaymentIntents/AttachPaymentMethodRequest.php @@ -0,0 +1,68 @@ + + * // Do an attach card transaction on the gateway + * $response = $gateway->attachCard(array( + * 'paymentMethod' => $paymentMethodId, + * 'customerReference' => $customerId, + * ))->send(); + * if ($response->isSuccessful()) { + * echo "Gateway attachCard was successful.\n"; + * // Find the card ID + * $methodId = $response->getCardReference(); + * echo "Method ID = " . $methodId . "\n"; + * } + * + * + * @see \Omnipay\Stripe\Message\PaymentIntents\CreatePaymentMethodRequest + * @see \Omnipay\Stripe\Message\PaymentIntents\CreateCustomerRequest + * @see \Omnipay\Stripe\Message\PaymentIntents\DetachPaymentMethodRequest + * @see \Omnipay\Stripe\Message\PaymentIntents\UpdatePaymentMethodRequest + * @link https://stripe.com/docs/api/payment_methods/attach + */ +class AttachPaymentMethodRequest extends AbstractRequest +{ + public function getData() + { + $data = []; + + $this->validate('customerReference'); + $this->validate('paymentMethod'); + + $data['customer'] = $this->getCustomerReference(); + + return $data; + } + + /** + * @inheritdoc + */ + public function getEndpoint() + { + return $this->endpoint.'/payment_methods/' . $this->getPaymentMethod() . '/attach'; + } + + /** + * @inheritdoc + */ + protected function createResponse($data, $headers = []) + { + return $this->response = new Response($this, $data, $headers); + } +} diff --git a/src/Message/PaymentIntents/AuthorizeRequest.php b/src/Message/PaymentIntents/AuthorizeRequest.php new file mode 100644 index 00000000..9eb53ee3 --- /dev/null +++ b/src/Message/PaymentIntents/AuthorizeRequest.php @@ -0,0 +1,374 @@ + + * // Create a gateway for the Stripe Gateway + * // (routes to GatewayFactory::create) + * $gateway = Omnipay::create('Stripe\PaymentIntents'); + * + * // Initialise the gateway + * $gateway->initialize(array( + * 'apiKey' => 'MyApiKey', + * )); + * + * // Create a payment method using a credit card object. + * // This card can be used for testing. + * $card = new CreditCard(array( + * 'firstName' => 'Example', + * 'lastName' => 'Customer', + * 'number' => '4242424242424242', + * 'expiryMonth' => '01', + * 'expiryYear' => '2020', + * 'cvv' => '123', + * 'email' => 'customer@example.com', + * 'billingAddress1' => '1 Scrubby Creek Road', + * 'billingCountry' => 'AU', + * 'billingCity' => 'Scrubby Creek', + * 'billingPostcode' => '4999', + * 'billingState' => 'QLD', + * )); + * + * $paymentMethod = $gateway->createCard($card)->send()->getCardReference(); + * + * // Code above can be skipped if you use Stripe.js and have a payment method reference + * // in the $paymentMethod variable already. + * + * // For backwards compatibility, it's also possible to use card and source references + * // as well as tokens. However, a data dictionary containing card data cannot + * // be used at this stage. + * + * // Also note the setting of a return url. This is needed for cards that require + * // the 3DS 2.0 authentication. If you do not set a return url, payment with such + * // cards will fail. + * + * // Do a purchase transaction on the gateway + * $paymentIntent = $gateway->authorize(array( + * 'amount' => '10.00', + * 'currency' => 'USD', + * 'description' => 'This is a test purchase transaction.', + * 'paymentMethod' => $paymentMethod, + * 'returnUrl' => $completePaymentUrl, + * 'confirm' => true, + * )); + * + * $paymentIntent = $paymentIntent->send(); + * + * // Alternatively, if you don't want to confirm it at one go for whatever reason, you + * // can use this code block below to confirm it. Otherwise, skip it. + * $paymentIntent = $gateway->confirm(array( + * 'returnUrl' => $completePaymentUrl + * 'paymentIntentReference' => $paymentIntent->getPaymentIntentReference(), + * )); + * + * $response = $paymentIntent->send(); + * + * // If you set the confirm to true when performing the authorize transaction, + * // resume here. + * + * // 3DS 2.0 time! + * if ($response->isRedirect()) { + * $response->redirect(); + * } else if ($response->isSuccessful()) { + * echo "Authorize transaction was successful!\n"; + * $sale_id = $response->getTransactionReference(); + * echo "Transaction reference = " . $sale_id . "\n"; + * } + * + * + * @see \Omnipay\Stripe\PaymentIntentsGateway + * @see \Omnipay\Stripe\Message\PaymentIntents\CreatePaymentMethodRequest + * @see \Omnipay\Stripe\Message\PaymentIntents\ConfirmPaymentIntentRequest + * @link https://stripe.com/docs/api/payment_intents + */ +class AuthorizeRequest extends AbstractRequest +{ + /** + * Set the confirm parameter. + * + * @param $value + */ + public function setConfirm($value) + { + $this->setParameter('confirm', $value); + } + + /** + * Get the confirm parameter. + * + * @return mixed + */ + public function getConfirm() + { + return $this->getParameter('confirm'); + } + + /** + * @return mixed + */ + public function getDestination() + { + return $this->getParameter('destination'); + } + + /** + * @param string $value + * + * @return AbstractRequest provides a fluent interface. + */ + public function setDestination($value) + { + return $this->setParameter('destination', $value); + } + + /** + * @return mixed + */ + public function getSource() + { + return $this->getParameter('source'); + } + + /** + * @param string $value + * + * @return AbstractRequest provides a fluent interface. + */ + public function setSource($value) + { + return $this->setParameter('source', $value); + } + + /** + * Connect only + * + * @return mixed + */ + public function getTransferGroup() + { + return $this->getParameter('transferGroup'); + } + + /** + * @param string $value + * + * @return AbstractRequest provides a fluent interface. + */ + public function setTransferGroup($value) + { + return $this->setParameter('transferGroup', $value); + } + + /** + * Connect only + * + * @return mixed + */ + public function getOnBehalfOf() + { + return $this->getParameter('onBehalfOf'); + } + + /** + * @param string $value + * + * @return AbstractRequest provides a fluent interface. + */ + public function setOnBehalfOf($value) + { + return $this->setParameter('onBehalfOf', $value); + } + + + /** + * @return string + * @throws \Omnipay\Common\Exception\InvalidRequestException + */ + public function getApplicationFee() + { + $money = $this->getMoney('applicationFee'); + + if ($money !== null) { + $moneyFormatter = new DecimalMoneyFormatter($this->getCurrencies()); + + return $moneyFormatter->format($money); + } + + return ''; + } + + /** + * Get the payment amount as an integer. + * + * @return integer + * @throws \Omnipay\Common\Exception\InvalidRequestException + */ + public function getApplicationFeeInteger() + { + $money = $this->getMoney('applicationFee'); + + if ($money !== null) { + return (integer) $money->getAmount(); + } + + return 0; + } + + /** + * @param string $value + * + * @return AbstractRequest provides a fluent interface. + */ + public function setApplicationFee($value) + { + return $this->setParameter('applicationFee', $value); + } + + /** + * @return mixed + */ + public function getStatementDescriptor() + { + return $this->getParameter('statementDescriptor'); + } + + /** + * @param string $value + * + * @return AbstractRequest provides a fluent interface. + */ + public function setStatementDescriptor($value) + { + $value = str_replace(array('<', '>', '"', '\''), '', $value); + + return $this->setParameter('statementDescriptor', $value); + } + + /** + * @return mixed + */ + public function getReceiptEmail() + { + return $this->getParameter('receipt_email'); + } + + /** + * @param mixed $email + * @return $this + */ + public function setReceiptEmail($email) + { + $this->setParameter('receipt_email', $email); + + return $this; + } + + /** + * @inheritdoc + */ + public function getData() + { + $this->validate('amount', 'currency'); + + $data = array(); + + $data['amount'] = $this->getAmountInteger(); + $data['currency'] = strtolower($this->getCurrency()); + $data['description'] = $this->getDescription(); + $data['metadata'] = $this->getMetadata(); + + if ($this->getStatementDescriptor()) { + $data['statement_descriptor'] = $this->getStatementDescriptor(); + } + if ($this->getDestination()) { + $data['transfer_data']['destination'] = $this->getDestination(); + } + + if ($this->getOnBehalfOf()) { + $data['on_behalf_of'] = $this->getOnBehalfOf(); + } + + if ($this->getApplicationFee()) { + $data['application_fee'] = $this->getApplicationFeeInteger(); + } + + if ($this->getTransferGroup()) { + $data['transfer_group'] = $this->getTransferGroup(); + } + + if ($this->getReceiptEmail()) { + $data['receipt_email'] = $this->getReceiptEmail(); + } + + if ($this->getPaymentMethod()) { + $data['payment_method'] = $this->getPaymentMethod(); + } elseif ($this->getSource()) { + $data['payment_method'] = $this->getSource(); + } elseif ($this->getCardReference()) { + $data['payment_method'] = $this->getCardReference(); + } elseif ($this->getToken()) { + $data['payment_method_data'] = [ + 'type' => 'card', + 'card' => ['token' => $this->getToken()], + ]; + } else { + // one of cardReference, token, or card is required + $this->validate('paymentMethod'); + } + + if ($this->getCustomerReference()) { + $data['customer'] = $this->getCustomerReference(); + } + + $data['confirmation_method'] = 'manual'; + $data['capture_method'] = 'manual'; + + $data['confirm'] = $this->getConfirm() ? 'true' : 'false'; + + if ($this->getConfirm()) { + $this->validate('returnUrl'); + $data['return_url'] = $this->getReturnUrl(); + } + + return $data; + } + + /** + * @inheritdoc + */ + public function getEndpoint() + { + return $this->endpoint.'/payment_intents'; + } + + /** + * @inheritdoc + */ + protected function createResponse($data, $headers = []) + { + return $this->response = new Response($this, $data, $headers); + } +} diff --git a/src/Message/PaymentIntents/CaptureRequest.php b/src/Message/PaymentIntents/CaptureRequest.php new file mode 100644 index 00000000..9baa3cdd --- /dev/null +++ b/src/Message/PaymentIntents/CaptureRequest.php @@ -0,0 +1,57 @@ + + * // Once the transaction has been authorized, we can capture it for final payment. + * $transaction = $gateway->capture(array( + * 'amount' => '10.00', + * 'currency' => 'AUD', + * )); + * $transaction->setPaymentMethod($paymentMethod); + * $response = $transaction->send(); + * + * + * @see AuthorizeRequest + * @link https://stripe.com/docs/api/payment_intents/capture + */ +class CaptureRequest extends AbstractRequest +{ + public function getData() + { + $this->validate('paymentIntentReference'); + + $data = array(); + + if ($amount = $this->getAmountInteger()) { + $data['amount_to_capture'] = $amount; + } + + return $data; + } + + public function getEndpoint() + { + return $this->endpoint.'/payment_intents/'.$this->getPaymentIntentReference().'/capture'; + } + + /** + * @inheritdoc + */ + protected function createResponse($data, $headers = []) + { + return $this->response = new Response($this, $data, $headers); + } +} diff --git a/src/Message/PaymentIntents/ConfirmPaymentIntentRequest.php b/src/Message/PaymentIntents/ConfirmPaymentIntentRequest.php new file mode 100644 index 00000000..da366040 --- /dev/null +++ b/src/Message/PaymentIntents/ConfirmPaymentIntentRequest.php @@ -0,0 +1,58 @@ +validate('paymentIntentReference'); + + $data = array(); + + if ($this->getReturnUrl()) { + $data['return_url'] = $this->getReturnUrl(); + } + + return $data; + } + + /** + * @inheritdoc + */ + public function getEndpoint() + { + return $this->endpoint.'/payment_intents/' . $this->getPaymentIntentReference() . '/confirm'; + } + + /** + * @inheritdoc + */ + protected function createResponse($data, $headers = []) + { + return $this->response = new Response($this, $data, $headers); + } +} diff --git a/src/Message/PaymentIntents/CreatePaymentMethodRequest.php b/src/Message/PaymentIntents/CreatePaymentMethodRequest.php new file mode 100644 index 00000000..86e39700 --- /dev/null +++ b/src/Message/PaymentIntents/CreatePaymentMethodRequest.php @@ -0,0 +1,131 @@ + + * // Create a credit card object + * // This card can be used for testing. + * $new_card = new CreditCard([ + * 'firstName' => 'Example', + * 'lastName' => 'Customer', + * 'number' => '5555555555554444', + * 'expiryMonth' => '01', + * 'expiryYear' => '2020', + * 'cvv' => '456', + * 'email' => 'customer@example.com', + * 'billingAddress1' => '1 Lower Creek Road', + * 'billingCountry' => 'AU', + * 'billingCity' => 'Upper Swan', + * 'billingPostcode' => '6999', + * 'billingState' => 'WA', + * ]); + * + * // Do a create card transaction on the gateway + * $response = $gateway->createCard(['card' => $new_card])->send(); + * if ($response->isSuccessful()) { + * echo "Gateway createCard was successful.\n"; + * // Find the card ID + * $method_id = $response->getCardReference(); + * echo "Method ID = " . $method_id . "\n"; + * } + * + * + * @see \Omnipay\Stripe\Message\PaymentIntents\AttachPaymentMethodRequest + * @see \Omnipay\Stripe\Message\PaymentIntents\DetachPaymentMethodRequest + * @see \Omnipay\Stripe\Message\PaymentIntents\UpdatePaymentMethodRequest + * @link https://stripe.com/docs/api/payment_methods/create + */ +class CreatePaymentMethodRequest extends AbstractRequest +{ + /** + * @inheritdoc + */ + public function getData() + { + $data = []; + + if ($this->getToken()) { + $data['card'] = ['token' => $this->getToken()]; + } elseif ($this->getCard()) { + $data['card'] = $this->getCardData(); + } else { + // one of token or card is required + $this->validate('card'); + } + + if ($billingDetails = $this->getBillingDetails()) { + $data['billing_details'] = $billingDetails; + } + + return $data; + } + + /** + * @inheritdoc + */ + public function getEndpoint() + { + return $this->endpoint.'/payment_methods'; + } + + /** + * @inheritdoc + */ + public function getCardData() + { + $data = parent::getCardData(); + + return [ + 'exp_month' => $data['exp_month'], + 'exp_year' => $data['exp_year'], + 'number' => $data['number'], + 'cvc' => $data['cvc'], + ]; + } + + /** + * Return an array of the billing details. + */ + public function getBillingDetails() + { + $data = parent::getCardData(); + + // Take care of optional data by filtering it out. + return array_filter([ + 'email' => $data['email'], + 'name' => $data['name'], + 'address' => array_filter([ + 'city' => $data['address_city'], + 'country' => $data['address_country'], + 'line1' => $data['address_line1'], + 'line2' => $data['address_line2'], + 'postal_code' => $data['address_zip'], + 'state' => $data['address_state'], + ]), + ]); + } + + /** + * @inheritdoc + */ + protected function createResponse($data, $headers = []) + { + return $this->response = new Response($this, $data, $headers); + } +} diff --git a/src/Message/PaymentIntents/DetachPaymentMethodRequest.php b/src/Message/PaymentIntents/DetachPaymentMethodRequest.php new file mode 100644 index 00000000..90c4f4b6 --- /dev/null +++ b/src/Message/PaymentIntents/DetachPaymentMethodRequest.php @@ -0,0 +1,60 @@ + + * // Do an attach card transaction on the gateway + * $response = $gateway->deleteCard(array( + * 'paymentMethod' => $paymentMethodId, + * ))->send(); + * if ($response->isSuccessful()) { + * echo "Gateway detachCard was successful.\n"; + * // Find the card ID + * $methodId = $response->getCardReference(); + * echo "Method ID = " . $methodId . "\n"; + * } + * + * + * @see \Omnipay\Stripe\Message\PaymentIntents\CreatePaymentMethodRequest + * @see \Omnipay\Stripe\Message\PaymentIntents\AttachPaymentMethodRequest + * @see \Omnipay\Stripe\Message\PaymentIntents\UpdatePaymentMethodRequest + * @link https://stripe.com/docs/api/payment_methods/detach + */ +class DetachPaymentMethodRequest extends AbstractRequest +{ + public function getData() + { + $this->validate('paymentMethod'); + + return []; + } + + /** + * @inheritdoc + */ + public function getEndpoint() + { + return $this->endpoint.'/payment_methods/' . $this->getPaymentMethod() . '/detach'; + } + + /** + * @inheritdoc + */ + protected function createResponse($data, $headers = []) + { + return $this->response = new Response($this, $data, $headers); + } +} diff --git a/src/Message/PaymentIntents/FetchPaymentIntentRequest.php b/src/Message/PaymentIntents/FetchPaymentIntentRequest.php new file mode 100644 index 00000000..2ea7425f --- /dev/null +++ b/src/Message/PaymentIntents/FetchPaymentIntentRequest.php @@ -0,0 +1,57 @@ +fetchPaymentIntent(array( + * 'paymentIntentReference' => $paymentIntentReference, + * )); + * + * $response = $paymentIntent->send(); + * + * if ($response->isSuccessful()) { + * // All done. Rejoice. + * } + * + * @link https://stripe.com/docs/api/payment_intents/retrieve + */ +class FetchPaymentIntentRequest extends AbstractRequest +{ + /** + * @inheritdoc + */ + public function getData() + { + $this->validate('paymentIntentReference'); + } + + /** + * @inheritdoc + */ + public function getHttpMethod() + { + return 'GET'; + } + + /** + * @inheritdoc + */ + public function getEndpoint() + { + return $this->endpoint . '/payment_intents/' . $this->getPaymentIntentReference(); + } + + /** + * @inheritdoc + */ + protected function createResponse($data, $headers = []) + { + return $this->response = new Response($this, $data, $headers); + } +} diff --git a/src/Message/PaymentIntents/PurchaseRequest.php b/src/Message/PaymentIntents/PurchaseRequest.php new file mode 100644 index 00000000..b3164a62 --- /dev/null +++ b/src/Message/PaymentIntents/PurchaseRequest.php @@ -0,0 +1,40 @@ +data['object']) && 'payment_intent' === $this->data['object']) { + return $this->data['status']; + } + + return null; + } + + /** + * Return true if the payment intent requires confirmation. + * + * @return bool + */ + public function requiresConfirmation() + { + return $this->getStatus() === 'requires_confirmation'; + } + + /** + * @inheritdoc + */ + public function getCardReference() + { + if (isset($this->data['object']) && 'payment_method' === $this->data['object']) { + if (!empty($this->data['id'])) { + return $this->data['id']; + } + } + + if (isset($this->data['object']) && 'payment_intent' === $this->data['object']) { + if (!empty($this->data['payment_method'])) { + return $this->data['payment_method']; + } + } + + return parent::getCardReference(); + } + + /** + * @inheritdoc + */ + public function getCustomerReference() + { + if (isset($this->data['object']) && 'payment_method' === $this->data['object']) { + if (!empty($this->data['customer'])) { + return $this->data['customer']; + } + } + + if (isset($this->data['object']) && 'payment_intent' === $this->data['object']) { + if (!empty($this->data['customer'])) { + return $this->data['customer']; + } + } + + return parent::getCustomerReference(); + } + + /** + * Get the capture method of a payment intents response. + * + * @return string|null + */ + public function getCaptureMethod() + { + if (isset($this->data['object']) && 'payment_intent' === $this->data['object']) { + return $this->data['capture_method']; + } + + return null; + } + + /** + * @inheritdoc + */ + public function getTransactionReference() + { + if (isset($this->data['object']) && 'payment_intent' === $this->data['object']) { + if (!empty($this->data['charges']['data'][0]['id'])) { + return $this->data['charges']['data'][0]['id']; + } + } + + return parent::getTransactionReference(); + } + + /** + * @inheritdoc + */ + public function isSuccessful() + { + if (isset($this->data['object']) && 'payment_intent' === $this->data['object']) { + return in_array($this->getStatus(), ['succeeded', 'requires_capture']); + } + + return parent::isSuccessful(); + } + + /** + * @inheritdoc + */ + public function isRedirect() + { + if ($this->getStatus() === 'requires_action') { + // Currently this gateway supports only manual confirmation, so any other + // next action types pretty much mean a failed transaction for us. + return (!empty($this->data['next_action']) && $this->data['next_action']['type'] === 'redirect_to_url'); + } + + return parent::isRedirect(); + } + + /** + * @inheritdoc + */ + public function getRedirectUrl() + { + return $this->isRedirect() ? $this->data['next_action']['redirect_to_url']['url'] : parent::getRedirectUrl(); + } + + /** + * Get the payment intent reference. + * + * @return string|null + */ + public function getPaymentIntentReference() + { + if (isset($this->data['object']) && 'payment_intent' === $this->data['object']) { + return $this->data['id']; + } + + return null; + } +} diff --git a/src/Message/PaymentIntents/UpdatePaymentMethodRequest.php b/src/Message/PaymentIntents/UpdatePaymentMethodRequest.php new file mode 100644 index 00000000..282397bc --- /dev/null +++ b/src/Message/PaymentIntents/UpdatePaymentMethodRequest.php @@ -0,0 +1,110 @@ +validate('paymentMethod'); + + $data = []; + + if ($this->getCard()) { + $data['card'] = $this->getCardData(); + $data['billing_details'] = $this->getBillingDetails(); + } else { + return array(); + } + + if ($metadata = $this->getMetadata()) { + $data['metadata'] = $metadata; + } + + return $data; + } + + public function getEndpoint() + { + return $this->endpoint.'/payment_methods/'.$this->getPaymentMethod(); + } + + /** + * Get the card data. + * + * This request uses a slightly different format for card data to + * the other requests and does not require the card data to be + * complete in full (or valid). + * + * @return array + */ + protected function getCardData() + { + $data = array(); + $card = $this->getCard(); + if (!empty($card)) { + if ($card->getExpiryMonth()) { + $data['exp_month'] = $card->getExpiryMonth(); + } + if ($card->getExpiryYear()) { + $data['exp_year'] = $card->getExpiryYear(); + } + } + + return $data; + } + + + /** + * Return an array of the billing details. + */ + public function getBillingDetails() + { + $data = parent::getCardData(); + + // Take care of optional data by filtering it out. + return array_filter([ + 'email' => $data['email'], + 'name' => $data['name'], + 'address' => array_filter([ + 'city' => $data['address_city'], + 'country' => $data['address_country'], + 'line1' => $data['address_line1'], + 'line2' => $data['address_line2'], + 'postal_code' => $data['address_zip'], + 'state' => $data['address_state'], + ]), + ]); + } + + /** + * @inheritdoc + */ + protected function createResponse($data, $headers = []) + { + return $this->response = new Response($this, $data, $headers); + } +} diff --git a/src/Message/Response.php b/src/Message/Response.php index a94e1e71..f80693ef 100644 --- a/src/Message/Response.php +++ b/src/Message/Response.php @@ -125,11 +125,13 @@ public function getCustomerReference() if (isset($this->data['object']) && 'customer' === $this->data['object']) { return $this->data['id']; } + if (isset($this->data['object']) && 'card' === $this->data['object']) { if (!empty($this->data['customer'])) { return $this->data['customer']; } } + if (isset($this->data['object']) && 'charge' === $this->data['object']) { if (!empty($this->data['customer'])) { return $this->data['customer']; @@ -159,11 +161,13 @@ public function getCardReference() return $this->data['id']; } } + if (isset($this->data['object']) && 'card' === $this->data['object']) { if (!empty($this->data['id'])) { return $this->data['id']; } } + if (isset($this->data['object']) && 'charge' === $this->data['object']) { if (! empty($this->data['source'])) { if (! empty($this->data['source']['id'])) { diff --git a/src/PaymentIntentsGateway.php b/src/PaymentIntentsGateway.php new file mode 100644 index 00000000..3dcee2c2 --- /dev/null +++ b/src/PaymentIntentsGateway.php @@ -0,0 +1,150 @@ +createRequest('\Omnipay\Stripe\Message\PaymentIntents\AuthorizeRequest', $parameters); + } + + /** + * @inheritdoc + * + * In reality, we're confirming the payment intent. + * This method exists as an alias to in line with how Omnipay interfaces define things. + * + * @return \Omnipay\Stripe\Message\PaymentIntents\ConfirmPaymentIntentRequest + */ + public function completeAuthorize(array $options = []) + { + return $this->confirm($options); + } + + /** + * @inheritdoc + * + * @return \Omnipay\Stripe\Message\PaymentIntents\CaptureRequest + */ + public function capture(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\PaymentIntents\CaptureRequest', $parameters); + } + + /** + * Confirm a Payment Intent. Use this to confirm a payment intent created by a Purchase or Authorize request. + * + * @param array $parameters + * @return \Omnipay\Stripe\Message\PaymentIntents\ConfirmPaymentIntentRequest + */ + public function confirm(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\PaymentIntents\ConfirmPaymentIntentRequest', $parameters); + } + + /** + * @inheritdoc + * + * @return \Omnipay\Stripe\Message\PaymentIntents\PurchaseRequest + */ + public function purchase(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\PaymentIntents\PurchaseRequest', $parameters); + } + + /** + * @inheritdoc + * + * In reality, we're confirming the payment intent. + * This method exists as an alias to in line with how Omnipay interfaces define things. + * + * @return \Omnipay\Stripe\Message\PaymentIntents\ConfirmPaymentIntentRequest + */ + public function completePurchase(array $options = []) + { + return $this->confirm($options); + } + + /** + * Fetch a payment intent. Use this to check the status of it. + * + * @return \Omnipay\Stripe\Message\PaymentIntents\FetchPaymentIntentRequest + */ + public function fetchPaymentIntent(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\PaymentIntents\FetchPaymentIntentRequest', $parameters); + } + + // + // Cards + // @link https://stripe.com/docs/api/payment_methods + // + + /** + * @inheritdoc + * + * @return \Omnipay\Stripe\Message\PaymentIntents\CreatePaymentMethodRequest + */ + public function createCard(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\PaymentIntents\CreatePaymentMethodRequest', $parameters); + } + + /** + * @inheritdoc + * + * @return \Omnipay\Stripe\Message\PaymentIntents\CreatePaymentMethodRequest + */ + public function attachCard(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\PaymentIntents\AttachPaymentMethodRequest', $parameters); + } + + /** + * @inheritdoc + * + * @return \Omnipay\Stripe\Message\PaymentIntents\UpdatePaymentMethodRequest + */ + public function updateCard(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\PaymentIntents\UpdatePaymentMethodRequest', $parameters); + } + + /** + * @inheritdoc + * + * @return \Omnipay\Stripe\Message\PaymentIntents\DetachPaymentMethodRequest + */ + public function deleteCard(array $parameters = array()) + { + return $this->createRequest('\Omnipay\Stripe\Message\PaymentIntents\DetachPaymentMethodRequest', $parameters); + } +} diff --git a/tests/GatewayTest.php b/tests/ChargeGatewayTest.php similarity index 99% rename from tests/GatewayTest.php rename to tests/ChargeGatewayTest.php index 3f5a6a68..5c4539b6 100644 --- a/tests/GatewayTest.php +++ b/tests/ChargeGatewayTest.php @@ -7,7 +7,7 @@ /** * @property Gateway gateway */ -class GatewayTest extends GatewayTestCase +class ChargeGatewayTest extends GatewayTestCase { public function setUp() { diff --git a/tests/Message/PaymentIntents/AbstractRequestTest.php b/tests/Message/PaymentIntents/AbstractRequestTest.php new file mode 100644 index 00000000..ef245be7 --- /dev/null +++ b/tests/Message/PaymentIntents/AbstractRequestTest.php @@ -0,0 +1,32 @@ +request = Mockery::mock('\Omnipay\Stripe\Message\PaymentIntents\AbstractRequest')->makePartial(); + $this->request->initialize(); + } + + public function testPaymentIntentReference() + { + $this->assertSame($this->request, $this->request->setPaymentIntentReference('abc123')); + $this->assertSame('abc123', $this->request->getPaymentIntentReference()); + } + + public function testPaymentMethodAlternatives() + { + $this->request->setCardReference('card_some_card'); + $this->assertSame('card_some_card', $this->request->getCardReference()); + $this->assertSame('card_some_card', $this->request->getPaymentMethod()); + } +} diff --git a/tests/Message/PaymentIntents/AttachPaymentMethodRequestTest.php b/tests/Message/PaymentIntents/AttachPaymentMethodRequestTest.php new file mode 100644 index 00000000..f3cb1d97 --- /dev/null +++ b/tests/Message/PaymentIntents/AttachPaymentMethodRequestTest.php @@ -0,0 +1,73 @@ +request = new AttachPaymentMethodRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setCustomerReference('someCustomer'); + $this->request->setPaymentMethod('pm_some_visa'); + } + + public function testEndpoint() + { + $this->assertSame('https://api.stripe.com/v1/payment_methods/pm_some_visa/attach', $this->request->getEndpoint()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The customerReference parameter is required + */ + public function testMissingCustomer() + { + $this->request->setCustomerReference(null); + $this->request->setPaymentMethod(null); + $this->request->getData(); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The paymentMethod parameter is required + */ + public function testMissingPaymentMethod() + { + $this->request->setPaymentMethod(null); + $this->request->getData(); + } + + public function testData() + { + $data = $this->request->getData(); + + $this->assertSame('someCustomer', $data['customer']); + } + + public function testSendSuccess() + { + $this->setMockHttpResponse('AttachPaymentMethodSuccess.txt'); + $response = $this->request->send(); + + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertSame('cus_3f2EpMK2kPm90g', $response->getCustomerReference()); + $this->assertSame('pm_1EUon32Tb35ankTnF6nuoRVE', $response->getCardReference()); + $this->assertNull($response->getMessage()); + } + + public function testSendFailure() + { + $this->setMockHttpResponse('AttachPaymentMethodFailure.txt'); + $response = $this->request->send(); + + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertNull($response->getCardReference()); + $this->assertSame('This PaymentMethod was previously used without being attached to a Customer or was detached from a Customer, and may not be used again.', $response->getMessage()); + } +} diff --git a/tests/Message/PaymentIntents/AuthorizeRequestTest.php b/tests/Message/PaymentIntents/AuthorizeRequestTest.php new file mode 100644 index 00000000..9e3b8858 --- /dev/null +++ b/tests/Message/PaymentIntents/AuthorizeRequestTest.php @@ -0,0 +1,162 @@ +request = new AuthorizeRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->initialize( + array( + 'amount' => '12.00', + 'currency' => 'USD', + 'paymentMethod' => 'pm_valid_payment_method', + 'description' => 'Order #42', + 'metadata' => array( + 'foo' => 'bar', + ), + 'applicationFee' => '1.00', + 'returnUrl' => 'complete-payment', + 'confirm' => true, + ) + ); + } + + public function testGetData() + { + $data = $this->request->getData(); + + $this->assertSame(1200, $data['amount']); + $this->assertSame('usd', $data['currency']); + $this->assertSame('Order #42', $data['description']); + $this->assertSame('manual', $data['capture_method']); + $this->assertSame('manual', $data['confirmation_method']); + $this->assertSame('pm_valid_payment_method', $data['payment_method']); + $this->assertSame(array('foo' => 'bar'), $data['metadata']); + $this->assertSame(100, $data['application_fee']); + } + + /** + * Test that providing card data won't work. + * + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The paymentMethod parameter is required + */ + public function testDataWithCardData() + { + $this->request->setPaymentMethod(null); + $this->request->setCard($this->getValidCard()); + $this->request->getData(); + } + + public function testDataWithCardReference() + { + $this->request->setPaymentMethod(null); + $this->request->setCardReference('card_visa'); + $data = $this->request->getData(); + + $this->assertSame('card_visa', $data['payment_method']); + } + + public function testDataWithSource() + { + $this->request->setPaymentMethod(null); + $this->request->setSource('src_visa'); + $data = $this->request->getData(); + + $this->assertSame('src_visa', $data['payment_method']); + } + + public function testDataWithToken() + { + $this->request->setPaymentMethod(null); + $this->request->setToken('tok_visa'); + $data = $this->request->getData(); + + $this->assertArrayHasKey('payment_method_data', $data); + } + + public function testDataWithCustomerReference() + { + $this->request->setCustomerReference('abc'); + $data = $this->request->getData(); + + $this->assertSame('abc', $data['customer']); + } + + + public function testDataWithStatementDescriptor() + { + $this->request->setStatementDescriptor('OMNIPAY'); + $data = $this->request->getData(); + + $this->assertSame('OMNIPAY', $data['statement_descriptor']); + } + + public function testDataWithDestination() + { + $this->request->setDestination('xyz'); + $data = $this->request->getData(); + + $this->assertSame('xyz', $data['transfer_data']['destination']); + } + + /** + * Confirming a payment intent without a return url would destroy the flow for 3DS 2.0, + * so let's make sure that setting confirm to true and skipping return url is + * not permitted. + * + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The returnUrl parameter is required + */ + public function testReturnUrlMustBeSetWhenConfirming() + { + $this->request->setReturnUrl(null); + $data = $this->request->getData(); + } + + /** + * If not confirming automatically, don't set the return url. + */ + public function testReturnUrlNotInData() + { + $this->request->setConfirm(false); + $data = $this->request->getData(); + $this->assertArrayNotHasKey('return_url', $data); + } + + public function testSendSuccessAndRequireConfirmation() + { + $this->setMockHttpResponse('AuthorizeSuccess.txt'); + /** @var PaymentIntentsResponse $response */ + $response = $this->request->send(); + + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertTrue($response->requiresConfirmation()); + $this->assertSame('manual', $response->getCaptureMethod()); + $this->assertSame('pm_1Euf5RFSbr6xR4YAwZ5fP28B', $response->getCardReference()); + $this->assertSame('req_8PDHeZazN2LwML', $response->getRequestId()); + $this->assertSame('cus_F1UMEEnT2OBgMg', $response->getCustomerReference()); + $this->assertNull($response->getMessage()); + } + + public function testSendError() + { + $this->setMockHttpResponse('AuthorizeFailure.txt'); + $response = $this->request->send(); + + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getCardReference()); + $this->assertSame('No such payment_method: pm_invalid_method', $response->getMessage()); + } +} diff --git a/tests/Message/PaymentIntents/CaptureRequestTest.php b/tests/Message/PaymentIntents/CaptureRequestTest.php new file mode 100644 index 00000000..77a64183 --- /dev/null +++ b/tests/Message/PaymentIntents/CaptureRequestTest.php @@ -0,0 +1,54 @@ +request = new CaptureRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setPaymentIntentReference('pi_valid_intent'); + } + + public function testEndpoint() + { + $this->assertSame('https://api.stripe.com/v1/payment_intents/pi_valid_intent/capture', $this->request->getEndpoint()); + } + + public function testAmount() + { + // default is no amount + $this->assertArrayNotHasKey('amount', $this->request->getData()); + + $this->request->setAmount('10.00'); + + $data = $this->request->getData(); + $this->assertSame(1000, $data['amount_to_capture']); + } + + public function testSendSuccess() + { + $this->setMockHttpResponse('CaptureSuccess.txt'); + $response = $this->request->send(); + + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('ch_1EZvfwFSbr6xR4YAWulsIcYV', $response->getTransactionReference()); + $this->assertSame('pm_1EZvfYFSbr6xR4YAGMpD5hNj', $response->getCardReference()); + $this->assertNull($response->getMessage()); + } + + public function testSendError() + { + $this->setMockHttpResponse('CaptureFailure.txt'); + $response = $this->request->send(); + + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertNull($response->getCardReference()); + $this->assertSame('This PaymentIntent could not be captured because it has already been captured.', $response->getMessage()); + } +} diff --git a/tests/Message/PaymentIntents/ConfirmPaymentIntentRequestTest.php b/tests/Message/PaymentIntents/ConfirmPaymentIntentRequestTest.php new file mode 100644 index 00000000..79ce9eb6 --- /dev/null +++ b/tests/Message/PaymentIntents/ConfirmPaymentIntentRequestTest.php @@ -0,0 +1,72 @@ +request = new ConfirmPaymentIntentRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setPaymentIntentReference('pi_valid_intent'); + $this->request->setReturnUrl('complete-payment-page'); + } + + public function testEndpoint() + { + $this->assertSame('https://api.stripe.com/v1/payment_intents/pi_valid_intent/confirm', $this->request->getEndpoint()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The paymentIntentReference parameter is required + */ + public function testPaymentIntent() + { + $this->request->setPaymentIntentReference(null); + $this->request->getData(); + } + + public function testRedirectUrl() + { + $data = $this->request->getData(); + + $this->assertSame('complete-payment-page', $data['return_url']); + } + + public function testConfirmSuccess() + { + $this->setMockHttpResponse('ConfirmIntentSuccess.txt'); + $response = $this->request->send(); + + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('ch_1Ev0a3FSbr6xR4YApjrlyFGi', $response->getTransactionReference()); + $this->assertSame('pm_1Ev0ZyFSbr6xR4YAX3vLBqEC', $response->getCardReference()); + $this->assertNull($response->getMessage()); + } + + public function testConfirmMissingRedirect() + { + $this->setMockHttpResponse('ConfirmIntentMissingRedirect.txt'); + $response = $this->request->send(); + + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertSame('pm_1Ev1CcFSbr6xR4YAuKuJgwEs', $response->getCardReference()); + } + + public function testConfirm3dsRedirect() + { + $this->setMockHttpResponse('ConfirmIntent3dsRedirect.txt'); + $response = $this->request->send(); + + $this->assertFalse($response->isSuccessful()); + $this->assertTrue($response->isRedirect()); + $redirectUrl = 'https://hooks.stripe.com/3d_secure_2_eap/begin_test/src_1Ev1M5FSbr6xR4YAg5qdBN6B/src_client_secret_FPr4a6wAiVNi6YrnuI7vah6H'; + $this->assertSame($redirectUrl, $response->getRedirectUrl()); + $this->assertSame('pm_1Ev1LzFSbr6xR4YA0TZ8jta0', $response->getCardReference()); + } + +} diff --git a/tests/Message/PaymentIntents/CreatePaymentMethodRequestTest.php b/tests/Message/PaymentIntents/CreatePaymentMethodRequestTest.php new file mode 100644 index 00000000..6100615a --- /dev/null +++ b/tests/Message/PaymentIntents/CreatePaymentMethodRequestTest.php @@ -0,0 +1,112 @@ +request = new CreatePaymentMethodRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setCard($this->getValidCard()); + } + + public function testEndpoint() + { + $this->assertSame('https://api.stripe.com/v1/payment_methods', $this->request->getEndpoint()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The card parameter is required + */ + public function testCard() + { + $this->request->setCard(null); + $this->request->getData(); + } + + public function testDataWithToken() + { + $this->request->setToken('xyz'); + $data = $this->request->getData(); + + $this->assertSame('xyz', $data['card']['token']); + } + + /** + * Impossible to use a card reference. + * + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The card parameter is required + */ + public function testDataWithCardReference() + { + $this->request->setCard(null); + $this->request->setCardReference('xyz'); + $data = $this->request->getData(); + + $this->assertSame('xyz', $data['source']); + } + + /** + * Impossible to use a source reference. + * + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The card parameter is required + */ + public function testDataWithSource() + { + $this->request->setCard(null); + $this->request->setSource('xyz'); + $data = $this->request->getData(); + + $this->assertSame('xyz', $data['source']); + } + + public function testDataWithCard() + { + $card = $this->getValidCard(); + $this->request->setCard($card); + $data = $this->request->getData(); + + $this->assertSame($card['number'], $data['card']['number']); + $this->assertSame($card['billingAddress1'], $data['billing_details']['address']['line1']); + $this->assertSame($card['firstName'] . ' ' . $card['lastName'], $data['billing_details']['name']); + } + + public function testSendSuccess() + { + $this->setMockHttpResponse('CreatePaymentMethodSuccess.txt'); + $response = $this->request->send(); + + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertSame(null, $response->getCustomerReference()); + $this->assertSame('pm_1EUon32Tb35ankTnF6nuoRVE', $response->getCardReference()); + $this->assertNull($response->getMessage()); + } + + public function testSendFailure() + { + $this->setMockHttpResponse('CreatePaymentMethodFailure.txt'); + $response = $this->request->send(); + + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertNull($response->getCardReference()); + $this->assertSame('Invalid integer: xyz', $response->getMessage()); + } + + public function testCardWithoutEmail() + { + $card = $this->getValidCard(); + $this->request->setCard($card); + $data = $this->request->getData(); + + $this->assertArrayNotHasKey('email', $data['billing_details']); + } +} diff --git a/tests/Message/PaymentIntents/DetachPaymentMethodRequestTest.php b/tests/Message/PaymentIntents/DetachPaymentMethodRequestTest.php new file mode 100644 index 00000000..95503232 --- /dev/null +++ b/tests/Message/PaymentIntents/DetachPaymentMethodRequestTest.php @@ -0,0 +1,59 @@ +request = new DetachPaymentMethodRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setPaymentMethod('pm_some_visa'); + } + + public function testEndpoint() + { + $this->assertSame('https://api.stripe.com/v1/payment_methods/pm_some_visa/detach', $this->request->getEndpoint()); + } + + /** + * @expectedException \Omnipay\Common\Exception\InvalidRequestException + * @expectedExceptionMessage The paymentMethod parameter is required + */ + public function testMissingPaymentMethod() + { + $this->request->setPaymentMethod(null); + $this->request->getData(); + } + + public function testData() + { + $this->assertEmpty($this->request->getData()); + } + + public function testSendSuccess() + { + $this->setMockHttpResponse('DetachPaymentMethodSuccess.txt'); + $response = $this->request->send(); + + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertSame('cus_3f2EpMK2kPm90g', $response->getCustomerReference()); + $this->assertSame('pm_1EUon32Tb35ankTnF6nuoRVE', $response->getCardReference()); + $this->assertNull($response->getMessage()); + } + + public function testSendFailure() + { + $this->setMockHttpResponse('DetachPaymentMethodFailure.txt'); + $response = $this->request->send(); + + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertNull($response->getCardReference()); + $this->assertSame('The payment method you provided is not attached to a customer so detachment is impossible.', $response->getMessage()); + } +} diff --git a/tests/Message/PaymentIntents/FetchPaymentIntentRequestTest.php b/tests/Message/PaymentIntents/FetchPaymentIntentRequestTest.php new file mode 100644 index 00000000..fc1c7975 --- /dev/null +++ b/tests/Message/PaymentIntents/FetchPaymentIntentRequestTest.php @@ -0,0 +1,63 @@ +request = new FetchPaymentIntentRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setPaymentIntentReference('pi_valid_intent'); + } + + public function testEndpoint() + { + $this->assertSame('https://api.stripe.com/v1/payment_intents/pi_valid_intent', $this->request->getEndpoint()); + } + + public function testHttpMethod() + { + $this->assertSame('GET', $this->request->getHttpMethod()); + } + + /** + * Manually fetching an intent would most likely occur after 3DS authentication + */ + public function test3dsSuccess() + { + $this->setMockHttpResponse('FetchIntentReadyToConfirm.txt'); + $response = $this->request->send(); + $this->assertTrue($response->requiresConfirmation()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertSame('requires_confirmation', $response->getStatus()); + $this->assertSame('pi_1Ev1ezFSbr6xR4YAtM76y2kZ', $response->getPaymentIntentReference()); + } + + /** + * Most common case would be failed 3DS authentication. + */ + public function testPaymentMethodRequired() + { + $this->setMockHttpResponse('FetchIntentPaymentMethodRequired.txt'); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getCustomerReference()); + $this->assertSame('requires_payment_method', $response->getStatus()); + $this->assertSame('pi_1Ev1ZFFSbr6xR4YAlcdtdqGH', $response->getPaymentIntentReference()); + } + + public function testSendFailure() + { + $this->setMockHttpResponse('FetchIntentFailure.txt'); + $response = $this->request->send(); + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertNull($response->getCustomerReference()); + $this->assertSame('No such payment_intent: pi_1EUon12Tb35ankTnZyvC3sSdE', $response->getMessage()); + } +} diff --git a/tests/Message/PaymentIntents/Mock/AttachPaymentMethodFailure.txt b/tests/Message/PaymentIntents/Mock/AttachPaymentMethodFailure.txt new file mode 100644 index 00000000..51a0a0d0 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/AttachPaymentMethodFailure.txt @@ -0,0 +1,16 @@ +HTTP/1.1 402 Payment Required +Server: nginx +Date: Tue, 26 Feb 2013 16:17:02 GMT +Content-Type: application/json;charset=utf-8 +Content-Length: 139 +Connection: keep-alive +Access-Control-Max-Age: 300 +Access-Control-Allow-Credentials: true +Cache-Control: no-cache, no-store + +{ + "error": { + "message": "This PaymentMethod was previously used without being attached to a Customer or was detached from a Customer, and may not be used again.", + "type": "invalid_request_error" + } +} \ No newline at end of file diff --git a/tests/Message/PaymentIntents/Mock/AttachPaymentMethodSuccess.txt b/tests/Message/PaymentIntents/Mock/AttachPaymentMethodSuccess.txt new file mode 100644 index 00000000..db186a18 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/AttachPaymentMethodSuccess.txt @@ -0,0 +1,50 @@ +HTTP/1.1 200 OK +Server: nginx +Date: Tue, 26 Feb 2013 16:11:12 GMT +Content-Type: application/json;charset=utf-8 +Connection: keep-alive +Access-Control-Max-Age: 300 +Access-Control-Allow-Credentials: true +Cache-Control: no-cache, no-store + +{ + "id": "pm_1EUon32Tb35ankTnF6nuoRVE", + "object": "payment_method", + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": null, + "name": null, + "phone": null + }, + "card": { + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": null + }, + "country": "US", + "exp_month": 8, + "exp_year": 2020, + "fingerprint": "9OyiQNfcCMaD1b7P", + "funding": "credit", + "generated_from": null, + "last4": "4242", + "three_d_secure_usage": { + "supported": true + }, + "wallet": null + }, + "created": 1556603165, + "customer": "cus_3f2EpMK2kPm90g", + "livemode": false, + "metadata": {}, + "type": "card" +} diff --git a/tests/Message/PaymentIntents/Mock/AuthorizeFailure.txt b/tests/Message/PaymentIntents/Mock/AuthorizeFailure.txt new file mode 100644 index 00000000..9b793a0c --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/AuthorizeFailure.txt @@ -0,0 +1,24 @@ +HTTP/2 400 +server: nginx +date: Thu, 11 Jul 2019 08:46:44 GMT +content-type: application/json +content-length: 247 +access-control-allow-credentials: true +access-control-allow-methods: GET, POST, HEAD, OPTIONS, DELETE +access-control-allow-origin: * +access-control-expose-headers: Request-Id, Stripe-Manage-Version, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required +access-control-max-age: 300 +cache-control: no-cache, no-store +request-id: req_IznB7F29VYnxZj +stripe-version: 2019-03-14 +strict-transport-security: max-age=31556926; includeSubDomains; preload + +{ + "error": { + "code": "resource_missing", + "doc_url": "https://stripe.com/docs/error-codes/resource-missing", + "message": "No such payment_method: pm_invalid_method", + "param": "payment_method", + "type": "invalid_request_error" + } +} \ No newline at end of file diff --git a/tests/Message/PaymentIntents/Mock/AuthorizeSuccess.txt b/tests/Message/PaymentIntents/Mock/AuthorizeSuccess.txt new file mode 100644 index 00000000..5ca8f914 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/AuthorizeSuccess.txt @@ -0,0 +1,60 @@ +HTTP/1.1 200 OK +Server: nginx +Date: Fri, 15 Feb 2013 18:25:28 GMT +Content-Type: application/json;charset=utf-8 +Content-Length: 995 +Connection: keep-alive +Cache-Control: no-cache, no-store +Request-Id: req_8PDHeZazN2LwML +Access-Control-Allow-Credentials: true +Access-Control-Max-Age: 300 + +{ + "id": "pi_1Euf5UFSbr6xR4YAp9PPTxza", + "object": "payment_intent", + "amount": 8000, + "amount_capturable": 0, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "charges": { + "object": "list", + "data": [], + "has_more": false, + "total_count": 0, + "url": "\/v1\/charges?payment_intent=pi_1Euf5UFSbr6xR4YAp9PPTxza" + }, + "client_secret": "pi_1Euf5UFSbr6xR4YAp9PPTxza_secret_QjDdAp77yVbiJoyJ92mXx76F7", + "confirmation_method": "manual", + "created": 1562762396, + "currency": "usd", + "customer": "cus_F1UMEEnT2OBgMg", + "description": "Order #153", + "invoice": null, + "last_payment_error": null, + "livemode": false, + "metadata": { + "order_id": "153", + "order_number": "d1defe5bbef31c3472b06d3c8c723baf", + "transaction_reference": "386b931a5e2bdb0a216749d488367b94", + "client_ip": "::1" + }, + "next_action": null, + "on_behalf_of": null, + "payment_method": "pm_1Euf5RFSbr6xR4YAwZ5fP28B", + "payment_method_types": [ + "card" + ], + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "status": "requires_confirmation", + "transfer_data": null, + "transfer_group": null +} \ No newline at end of file diff --git a/tests/Message/PaymentIntents/Mock/CaptureFailure.txt b/tests/Message/PaymentIntents/Mock/CaptureFailure.txt new file mode 100644 index 00000000..362cb9a0 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/CaptureFailure.txt @@ -0,0 +1,23 @@ +HTTP/2 400 +server: nginx +date: Thu, 11 Jul 2019 08:46:44 GMT +content-type: application/json +content-length: 247 +access-control-allow-credentials: true +access-control-allow-methods: GET, POST, HEAD, OPTIONS, DELETE +access-control-allow-origin: * +access-control-expose-headers: Request-Id, Stripe-Manage-Version, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required +access-control-max-age: 300 +cache-control: no-cache, no-store +request-id: req_IznB7F29VYnxZj +stripe-version: 2019-03-14 +strict-transport-security: max-age=31556926; includeSubDomains; preload + +{ + "error": { + "code": "payment_intent_unexpected_state", + "doc_url": "https://stripe.com/docs/error-codes/payment-intent-unexpected-state", + "message": "This PaymentIntent could not be captured because it has already been captured.", + "type": "invalid_request_error" + } +} \ No newline at end of file diff --git a/tests/Message/PaymentIntents/Mock/CaptureSuccess.txt b/tests/Message/PaymentIntents/Mock/CaptureSuccess.txt new file mode 100644 index 00000000..6c1ae410 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/CaptureSuccess.txt @@ -0,0 +1,170 @@ +HTTP/1.1 200 OK +Server: nginx +Date: Fri, 15 Feb 2013 18:25:28 GMT +Content-Type: application/json;charset=utf-8 +Content-Length: 995 +Connection: keep-alive +Cache-Control: no-cache, no-store +Request-Id: req_8PDHeZazN2LwML +Access-Control-Allow-Credentials: true +Access-Control-Max-Age: 300 + +{ + "id": "pi_1EUon22Tb35ankTnMW9GNjSh", + "object": "payment_intent", + "amount": 8000, + "amount_capturable": 0, + "amount_received": 8000, + "application": null, + "application_fee_amount": null, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "charges": { + "object": "list", + "data": [ + { + "id": "ch_1EZvfwFSbr6xR4YAWulsIcYV", + "object": "charge", + "amount": 8000, + "amount_refunded": 2000, + "application": null, + "application_fee": null, + "application_fee_amount": null, + "balance_transaction": "txn_1EZvjKFSbr6xR4YAvqraMGP8", + "billing_details": { + "address": { + "city": "New York", + "country": "United States" + }, + "email": "some@person.com", + "name": "Jeff Bridge", + "phone": null + }, + "captured": true, + "created": 1557821272, + "currency": "usd", + "customer": "cus_F1UMEEnT2OBgMg", + "description": "Order #69", + "destination": null, + "dispute": null, + "failure_code": null, + "failure_message": null, + "fraud_details": {}, + "invoice": null, + "livemode": false, + "metadata": { + "order_id": "69", + "order_number": "47eae2af9d6f75b51e7111e27a43617b", + "transaction_reference": "8e914cb212f2e4c2a83e280d8b99488a", + "client_ip": "::1" + }, + "on_behalf_of": null, + "order": null, + "outcome": { + "network_status": "approved_by_network", + "reason": null, + "risk_level": "normal", + "risk_score": 38, + "rule": "allow_if_3ds_authenticated_liability_shift", + "seller_message": "Payment complete.", + "type": "authorized" + }, + "paid": true, + "payment_intent": "pi_1EUon22Tb35ankTnMW9GNjSh", + "payment_method": "pm_1EZvfYFSbr6xR4YAGMpD5hNj", + "payment_method_details": { + "card": { + "brand": "visa", + "checks": { + "address_line1_check": "pass", + "address_postal_code_check": "pass", + "cvc_check": "pass" + }, + "country": "IE", + "exp_month": 12, + "exp_year": 2020, + "fingerprint": "TLkivWVGoP3a2M2U", + "funding": "credit", + "last4": "3220", + "three_d_secure": { + "authenticated": true, + "succeeded": true, + "version": "2.1.0" + }, + "wallet": null + }, + "type": "card" + }, + "receipt_email": null, + "receipt_number": null, + "receipt_url": "https://pay.stripe.com/receipts/acct_1AjnbxFSbr6xR4YA/ch_1EZvfwFSbr6xR4YAWulsIcYV/rcpt_F43njL6DofvVuE7tlNDARemskoCJxff", + "refunded": false, + "refunds": { + "object": "list", + "data": [ + { + "id": "re_1EZvjaFSbr6xR4YAbdaX3k3R", + "object": "refund", + "amount": 2000, + "balance_transaction": "txn_1EZvjaFSbr6xR4YAtzwsSxhk", + "charge": "ch_1EZvfwFSbr6xR4YAWulsIcYV", + "created": 1557821498, + "currency": "usd", + "metadata": {}, + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/charges/ch_1EZvfwFSbr6xR4YAWulsIcYV/refunds" + }, + "review": null, + "shipping": null, + "source": null, + "source_transfer": null, + "statement_descriptor": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/charges?payment_intent=pi_1EUon22Tb35ankTnMW9GNjSh" + }, + "client_secret": "pi_1EUon22Tb35ankTnMW9GNjSh_secret_kxK3CBky2Uex0ctbsFxbokHyu", + "confirmation_method": "manual", + "created": 1557821043, + "currency": "usd", + "customer": "cus_F1UMEEnT2OBgMg", + "description": "Order #69", + "invoice": null, + "last_payment_error": null, + "livemode": false, + "metadata": { + "order_id": "69", + "order_number": "47eae2af9d6f75b51e7111e27a43617b", + "transaction_reference": "8e914cb212f2e4c2a83e280d8b99488a", + "client_ip": "::1" + }, + "next_action": null, + "on_behalf_of": null, + "payment_method": "pm_1EZvfYFSbr6xR4YAGMpD5hNj", + "payment_method_types": [ + "card" + ], + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null +} \ No newline at end of file diff --git a/tests/Message/PaymentIntents/Mock/ConfirmIntent3dsRedirect.txt b/tests/Message/PaymentIntents/Mock/ConfirmIntent3dsRedirect.txt new file mode 100644 index 00000000..5173c90e --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/ConfirmIntent3dsRedirect.txt @@ -0,0 +1,65 @@ +HTTP/1.1 200 OK +Server: nginx +Date: Sun, 05 May 2013 08:51:15 GMT +Content-Type: application/json;charset=utf-8 +Content-Length: 997 +Connection: keep-alive +Cache-Control: no-cache, no-store +Access-Control-Max-Age: 300 +Access-Control-Allow-Credentials: true + +{ + "id": "pi_1Ev1M1FSbr6xR4YAgJIBBVX0", + "object": "payment_intent", + "amount": 8000, + "amount_capturable": 0, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "charges": { + "object": "list", + "data": [], + "has_more": false, + "total_count": 0, + "url": "\/v1\/charges?payment_intent=pi_1Ev1M1FSbr6xR4YAgJIBBVX0" + }, + "client_secret": "pi_1Ev1M1FSbr6xR4YAgJIBBVX0_secret_MfGgtbEAM6GZ4JyquqbC09FXC", + "confirmation_method": "manual", + "created": 1562847989, + "currency": "usd", + "customer": "cus_Q8sHn93nAzgdn1", + "description": "Order #184", + "invoice": null, + "last_payment_error": null, + "livemode": false, + "metadata": { + "order_id": "184", + "order_number": "fd17b4d8d756814bc6a258ba578fc359", + "transaction_reference": "939185d93ad0634402cbe45b833e7428", + "client_ip": "::1" + }, + "next_action": { + "redirect_to_url": { + "return_url": "http:\/\/this-is-a-test-site.test\/complete-payment?foo=bar", + "url": "https:\/\/hooks.stripe.com\/3d_secure_2_eap\/begin_test\/src_1Ev1M5FSbr6xR4YAg5qdBN6B\/src_client_secret_FPr4a6wAiVNi6YrnuI7vah6H" + }, + "type": "redirect_to_url" + }, + "on_behalf_of": null, + "payment_method": "pm_1Ev1LzFSbr6xR4YA0TZ8jta0", + "payment_method_types": [ + "card" + ], + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "status": "requires_action", + "transfer_data": null, + "transfer_group": null +} diff --git a/tests/Message/PaymentIntents/Mock/ConfirmIntentMissingRedirect.txt b/tests/Message/PaymentIntents/Mock/ConfirmIntentMissingRedirect.txt new file mode 100644 index 00000000..018718dc --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/ConfirmIntentMissingRedirect.txt @@ -0,0 +1,65 @@ +HTTP/1.1 200 OK +Server: nginx +Date: Sun, 05 May 2013 08:51:15 GMT +Content-Type: application/json;charset=utf-8 +Content-Length: 997 +Connection: keep-alive +Cache-Control: no-cache, no-store +Access-Control-Max-Age: 300 +Access-Control-Allow-Credentials: true + +{ + "id": "pi_1Ev1CeFSbr6xR4YAbVhiBUv0", + "object": "payment_intent", + "amount": 8000, + "amount_capturable": 0, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "charges": { + "object": "list", + "data": [], + "has_more": false, + "total_count": 0, + "url": "\/v1\/charges?payment_intent=pi_1Ev1CeFSbr6xR4YAbVhiBUv0" + }, + "client_secret": "pi_1Ev1CeFSbr6xR4YAbVhiBUv0_secret_E8pK2lfYBh00cUEPMuTUrrqqR", + "confirmation_method": "manual", + "created": 1562847408, + "currency": "usd", + "customer": null, + "description": "Order #184", + "invoice": null, + "last_payment_error": null, + "livemode": false, + "metadata": { + "order_id": "184", + "order_number": "fd17b4d8d756814bc6a258ba578fc359", + "transaction_reference": "9d60ca0be3cc29276ddd5462be1d07a3", + "client_ip": "::1" + }, + "next_action": { + "type": "use_stripe_sdk", + "use_stripe_sdk": { + "type": "three_d_secure_redirect", + "stripe_js": "https:\/\/hooks.stripe.com\/3d_secure_2_eap\/begin_test\/src_1Ev1CiFSbr6xR4YAAz2cQKVv\/src_client_secret_FPquGxLPzcJz5ToIUwtRRsO3" + } + }, + "on_behalf_of": null, + "payment_method": "pm_1Ev1CcFSbr6xR4YAuKuJgwEs", + "payment_method_types": [ + "card" + ], + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "status": "requires_action", + "transfer_data": null, + "transfer_group": null +} diff --git a/tests/Message/PaymentIntents/Mock/ConfirmIntentSuccess.txt b/tests/Message/PaymentIntents/Mock/ConfirmIntentSuccess.txt new file mode 100644 index 00000000..5ac027e3 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/ConfirmIntentSuccess.txt @@ -0,0 +1,150 @@ +HTTP/1.1 200 OK +Server: nginx +Date: Sun, 05 May 2013 08:51:15 GMT +Content-Type: application/json;charset=utf-8 +Content-Length: 997 +Connection: keep-alive +Cache-Control: no-cache, no-store +Access-Control-Max-Age: 300 +Access-Control-Allow-Credentials: true + +{ + "id": "pi_1Ev0a2FSbr6xR4YAsGQmFF0X", + "object": "payment_intent", + "amount": 8000, + "amount_capturable": 8000, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "charges": { + "object": "list", + "data": [{ + "id": "ch_1Ev0a3FSbr6xR4YApjrlyFGi", + "object": "charge", + "amount": 8000, + "amount_refunded": 0, + "application": null, + "application_fee": null, + "application_fee_amount": null, + "balance_transaction": null, + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": "somebody@somewhere.net", + "name": "Jack Beanstalk", + "phone": null + }, + "captured": false, + "created": 1562845015, + "currency": "usd", + "customer": null, + "description": "Order #182", + "destination": null, + "dispute": null, + "failure_code": null, + "failure_message": null, + "fraud_details": [], + "invoice": null, + "livemode": false, + "metadata": { + "order_id": "182", + "order_number": "936dd9e6904c4bb2a8f65837d1d6403c", + "transaction_reference": "09f0cd14d0594e76ca53b78e98f80414", + "client_ip": "::1" + }, + "on_behalf_of": null, + "order": null, + "outcome": { + "network_status": "approved_by_network", + "reason": null, + "risk_level": "normal", + "risk_score": 17, + "seller_message": "Payment complete.", + "type": "authorized" + }, + "paid": true, + "payment_intent": "pi_1Ev0a2FSbr6xR4YAsGQmFF0X", + "payment_method": "pm_1Ev0ZyFSbr6xR4YAX3vLBqEC", + "payment_method_details": { + "card": { + "brand": "amex", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": "pass" + }, + "country": "US", + "exp_month": 12, + "exp_year": 2020, + "fingerprint": "fHKFepx6M3kreij5", + "funding": "credit", + "last4": "0005", + "three_d_secure": null, + "wallet": null + }, + "type": "card" + }, + "receipt_email": null, + "receipt_number": null, + "receipt_url": "https:\/\/pay.stripe.com\/receipts\/acct_1AjnbxFSbr6xR4YA\/ch_1Ev0a3FSbr6xR4YApjrlyFGi\/rcpt_FPqGKvHPhVfeinM9z4h2lTp3LleIV3c", + "refunded": false, + "refunds": { + "object": "list", + "data": [], + "has_more": false, + "total_count": 0, + "url": "\/v1\/charges\/ch_1Ev0a3FSbr6xR4YApjrlyFGi\/refunds" + }, + "review": null, + "shipping": null, + "source": null, + "source_transfer": null, + "statement_descriptor": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + }], + "has_more": false, + "total_count": 1, + "url": "\/v1\/charges?payment_intent=pi_1Ev0a2FSbr6xR4YAsGQmFF0X" + }, + "client_secret": "pi_1Ev0a2FSbr6xR4YAsGQmFF0X_secret_CWVHEZ8cOk21GTABOjWHBYLt0", + "confirmation_method": "manual", + "created": 1562845014, + "currency": "usd", + "customer": null, + "description": "Order #182", + "invoice": null, + "last_payment_error": null, + "livemode": false, + "metadata": { + "order_id": "182", + "order_number": "936dd9e6904c4bb2a8f65837d1d6403c", + "transaction_reference": "09f0cd14d0594e76ca53b78e98f80414", + "client_ip": "::1" + }, + "next_action": null, + "on_behalf_of": null, + "payment_method": "pm_1Ev0ZyFSbr6xR4YAX3vLBqEC", + "payment_method_types": [ + "card" + ], + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null +} diff --git a/tests/Message/PaymentIntents/Mock/CreatePaymentMethodFailure.txt b/tests/Message/PaymentIntents/Mock/CreatePaymentMethodFailure.txt new file mode 100644 index 00000000..fe0121b9 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/CreatePaymentMethodFailure.txt @@ -0,0 +1,19 @@ +HTTP/1.1 402 Payment Required +Server: nginx +Date: Tue, 26 Feb 2013 16:17:02 GMT +Content-Type: application/json;charset=utf-8 +Content-Length: 139 +Connection: keep-alive +Access-Control-Max-Age: 300 +Access-Control-Allow-Credentials: true +Cache-Control: no-cache, no-store + +{ + "error": { + "code": "parameter_invalid_integer", + "doc_url": "https://stripe.com/docs/error-codes/parameter-invalid-integer", + "message": "Invalid integer: xyz", + "param": "card[exp_year]", + "type": "invalid_request_error" + } +} \ No newline at end of file diff --git a/tests/Message/PaymentIntents/Mock/CreatePaymentMethodSuccess.txt b/tests/Message/PaymentIntents/Mock/CreatePaymentMethodSuccess.txt new file mode 100644 index 00000000..697b8eda --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/CreatePaymentMethodSuccess.txt @@ -0,0 +1,50 @@ +HTTP/1.1 200 OK +Server: nginx +Date: Tue, 26 Feb 2013 16:11:12 GMT +Content-Type: application/json;charset=utf-8 +Connection: keep-alive +Access-Control-Max-Age: 300 +Access-Control-Allow-Credentials: true +Cache-Control: no-cache, no-store + +{ + "id": "pm_1EUon32Tb35ankTnF6nuoRVE", + "object": "payment_method", + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": null, + "name": null, + "phone": null + }, + "card": { + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": null + }, + "country": "US", + "exp_month": 8, + "exp_year": 2020, + "fingerprint": "9OyiQNfcCMaD1b7P", + "funding": "credit", + "generated_from": null, + "last4": "4242", + "three_d_secure_usage": { + "supported": true + }, + "wallet": null + }, + "created": 1556603165, + "customer": null, + "livemode": false, + "metadata": {}, + "type": "card" +} \ No newline at end of file diff --git a/tests/Message/PaymentIntents/Mock/DetachPaymentMethodFailure.txt b/tests/Message/PaymentIntents/Mock/DetachPaymentMethodFailure.txt new file mode 100644 index 00000000..1d4ee997 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/DetachPaymentMethodFailure.txt @@ -0,0 +1,16 @@ +HTTP/1.1 402 Payment Required +Server: nginx +Date: Tue, 26 Feb 2013 16:17:02 GMT +Content-Type: application/json;charset=utf-8 +Content-Length: 139 +Connection: keep-alive +Access-Control-Max-Age: 300 +Access-Control-Allow-Credentials: true +Cache-Control: no-cache, no-store + +{ + "error": { + "message": "The payment method you provided is not attached to a customer so detachment is impossible.", + "type": "invalid_request_error" + } +} \ No newline at end of file diff --git a/tests/Message/PaymentIntents/Mock/DetachPaymentMethodSuccess.txt b/tests/Message/PaymentIntents/Mock/DetachPaymentMethodSuccess.txt new file mode 100644 index 00000000..db186a18 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/DetachPaymentMethodSuccess.txt @@ -0,0 +1,50 @@ +HTTP/1.1 200 OK +Server: nginx +Date: Tue, 26 Feb 2013 16:11:12 GMT +Content-Type: application/json;charset=utf-8 +Connection: keep-alive +Access-Control-Max-Age: 300 +Access-Control-Allow-Credentials: true +Cache-Control: no-cache, no-store + +{ + "id": "pm_1EUon32Tb35ankTnF6nuoRVE", + "object": "payment_method", + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": null, + "name": null, + "phone": null + }, + "card": { + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": null + }, + "country": "US", + "exp_month": 8, + "exp_year": 2020, + "fingerprint": "9OyiQNfcCMaD1b7P", + "funding": "credit", + "generated_from": null, + "last4": "4242", + "three_d_secure_usage": { + "supported": true + }, + "wallet": null + }, + "created": 1556603165, + "customer": "cus_3f2EpMK2kPm90g", + "livemode": false, + "metadata": {}, + "type": "card" +} diff --git a/tests/Message/PaymentIntents/Mock/FetchIntentFailure.txt b/tests/Message/PaymentIntents/Mock/FetchIntentFailure.txt new file mode 100644 index 00000000..c7325650 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/FetchIntentFailure.txt @@ -0,0 +1,24 @@ +HTTP/2 400 +server: nginx +date: Thu, 11 Jul 2019 08:46:44 GMT +content-type: application/json +content-length: 247 +access-control-allow-credentials: true +access-control-allow-methods: GET, POST, HEAD, OPTIONS, DELETE +access-control-allow-origin: * +access-control-expose-headers: Request-Id, Stripe-Manage-Version, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required +access-control-max-age: 300 +cache-control: no-cache, no-store +request-id: req_IznB7F29VYnxZj +stripe-version: 2019-03-14 +strict-transport-security: max-age=31556926; includeSubDomains; preload + +{ + "error": { + "code": "resource_missing", + "doc_url": "https://stripe.com/docs/error-codes/resource-missing", + "message": "No such payment_intent: pi_1EUon12Tb35ankTnZyvC3sSdE", + "param": "intent", + "type": "invalid_request_error" + } +} \ No newline at end of file diff --git a/tests/Message/PaymentIntents/Mock/FetchIntentPaymentMethodRequired.txt b/tests/Message/PaymentIntents/Mock/FetchIntentPaymentMethodRequired.txt new file mode 100644 index 00000000..742301f2 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/FetchIntentPaymentMethodRequired.txt @@ -0,0 +1,105 @@ +HTTP/1.1 200 OK +Server: nginx +Date: Sun, 05 May 2013 08:51:15 GMT +Content-Type: application/json;charset=utf-8 +Content-Length: 997 +Connection: keep-alive +Cache-Control: no-cache, no-store +Access-Control-Max-Age: 300 +Access-Control-Allow-Credentials: true + +{ + "id": "pi_1Ev1ZFFSbr6xR4YAlcdtdqGH", + "object": "payment_intent", + "amount": 8000, + "amount_capturable": 0, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "charges": { + "object": "list", + "data": [], + "has_more": false, + "total_count": 0, + "url": "\/v1\/charges?payment_intent=pi_1Ev1ZFFSbr6xR4YAlcdtdqGH" + }, + "client_secret": "pi_1Ev1ZFFSbr6xR4YAlcdtdqGH_secret_dpqra3YEDAA6JTVQdyZj8us0Q", + "confirmation_method": "manual", + "created": 1562848809, + "currency": "usd", + "customer": null, + "description": "Order #184", + "invoice": null, + "last_payment_error": { + "code": "payment_intent_authentication_failure", + "doc_url": "https:\/\/stripe.com\/docs\/error-codes\/payment-intent-authentication-failure", + "message": "The provided PaymentMethod has failed authentication. You can provide payment_method_data or a new PaymentMethod to attempt to fulfill this PaymentIntent again.", + "payment_method": { + "id": "pm_1Ev1ZCFSbr6xR4YA2vAxx9L7", + "object": "payment_method", + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": "some@email.com", + "name": "Just Guy", + "phone": null + }, + "card": { + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": "unchecked" + }, + "country": "IE", + "exp_month": 12, + "exp_year": 2020, + "fingerprint": "TLkivWVGoP3a2M2U", + "funding": "credit", + "generated_from": null, + "last4": "3220", + "three_d_secure_usage": { + "supported": true + }, + "wallet": null + }, + "created": 1562848806, + "customer": null, + "livemode": false, + "metadata": [], + "type": "card" + }, + "type": "invalid_request_error" + }, + "livemode": false, + "metadata": { + "order_id": "184", + "order_number": "fd17b4d8d756814bc6a258ba578fc359", + "transaction_reference": "4a846a6e34639f22926e14e283ff8f90", + "client_ip": "::1" + }, + "next_action": null, + "on_behalf_of": null, + "payment_method": null, + "payment_method_types": [ + "card" + ], + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null +} diff --git a/tests/Message/PaymentIntents/Mock/FetchIntentReadyToConfirm.txt b/tests/Message/PaymentIntents/Mock/FetchIntentReadyToConfirm.txt new file mode 100644 index 00000000..c5642084 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/FetchIntentReadyToConfirm.txt @@ -0,0 +1,59 @@ +HTTP/1.1 200 OK +Server: nginx +Date: Sun, 05 May 2013 08:51:15 GMT +Content-Type: application/json;charset=utf-8 +Content-Length: 997 +Connection: keep-alive +Cache-Control: no-cache, no-store +Access-Control-Max-Age: 300 +Access-Control-Allow-Credentials: true + +{ + "id": "pi_1Ev1ezFSbr6xR4YAtM76y2kZ", + "object": "payment_intent", + "amount": 8000, + "amount_capturable": 0, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "charges": { + "object": "list", + "data": [], + "has_more": false, + "total_count": 0, + "url": "\/v1\/charges?payment_intent=pi_1Ev1ezFSbr6xR4YAtM76y2kZ" + }, + "client_secret": "pi_1Ev1ezFSbr6xR4YAtM76y2kZ_secret_1LNKABAbQzLv0PLghVQ9KzLtJ", + "confirmation_method": "manual", + "created": 1562849165, + "currency": "usd", + "customer": null, + "description": "Order #184", + "invoice": null, + "last_payment_error": null, + "livemode": false, + "metadata": { + "order_id": "184", + "order_number": "fd17b4d8d756814bc6a258ba578fc359", + "transaction_reference": "4bd4f322cf005e954c78194633b58b0b", + "client_ip": "::1" + }, + "next_action": null, + "on_behalf_of": null, + "payment_method": "pm_1Ev1ewFSbr6xR4YAM7H9IPu8", + "payment_method_types": [ + "card" + ], + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "status": "requires_confirmation", + "transfer_data": null, + "transfer_group": null +} diff --git a/tests/Message/PaymentIntents/Mock/PurchaseSuccess.txt b/tests/Message/PaymentIntents/Mock/PurchaseSuccess.txt new file mode 100644 index 00000000..b7f92023 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/PurchaseSuccess.txt @@ -0,0 +1,155 @@ +HTTP/1.1 200 OK +Server: nginx +Date: Fri, 15 Feb 2013 18:25:28 GMT +Content-Type: application/json;charset=utf-8 +Content-Length: 995 +Connection: keep-alive +Cache-Control: no-cache, no-store +Request-Id: req_8PDHeZazN2LwML +Access-Control-Allow-Credentials: true +Access-Control-Max-Age: 300 + +{ + "id": "pi_1EW0FmFSbr6xR4YAvECSRCv2", + "object": "payment_intent", + "amount": 8000, + "amount_capturable": 0, + "amount_received": 8000, + "application": null, + "application_fee_amount": null, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "charges": { + "object": "list", + "data": [ + { + "id": "ch_1EW0FmFSbr6xR4YAZyURWxQe", + "object": "charge", + "amount": 8000, + "amount_refunded": 0, + "application": null, + "application_fee": null, + "application_fee_amount": null, + "balance_transaction": "txn_1EW0FnFSbr6xR4YAOVasO6Eu", + "billing_details": { + "address": { + "city": "Riga", + "country": "United States", + "line1": "GARRISON DRIVE 60837", + "line2": null, + "postal_code": "97702", + "state": null + }, + "email": "andris@shift.lv", + "name": "Janice Friend", + "phone": null + }, + "captured": true, + "created": 1556885558, + "currency": "usd", + "customer": "cus_F0026biLhRIcO9", + "description": "Order #34", + "destination": null, + "dispute": null, + "failure_code": null, + "failure_message": null, + "fraud_details": { + }, + "invoice": null, + "livemode": false, + "metadata": { + "order_id": "34", + "order_number": "aaefd8ec96095c47ed0c665666c3c768", + "transaction_reference": "84aaac664c7048000146d3a88b5f0081", + "client_ip": "::1" + }, + "on_behalf_of": null, + "order": null, + "outcome": { + "network_status": "approved_by_network", + "reason": null, + "risk_level": "normal", + "risk_score": 21, + "seller_message": "Payment complete.", + "type": "authorized" + }, + "paid": true, + "payment_intent": "pi_1EW0FmFSbr6xR4YAvECSRCv2", + "payment_method": "pm_1EW0FPFSbr6xR4YAZOSMHIOE", + "payment_method_details": { + "card": { + "brand": "visa", + "checks": { + "address_line1_check": "pass", + "address_postal_code_check": "pass", + "cvc_check": "pass" + }, + "country": "US", + "description": "Visa Classic", + "exp_month": 12, + "exp_year": 2020, + "fingerprint": "ZpBtWK0wNH3oi8mw", + "funding": "credit", + "last4": "4242", + "three_d_secure": null, + "wallet": null + }, + "type": "card" + }, + "receipt_email": null, + "receipt_number": null, + "receipt_url": "https://pay.stripe.com/receipts/acct_1AjnbxFSbr6xR4YA/ch_1EW0FmFSbr6xR4YAZyURWxQe/rcpt_F00G6tmZch7lV8HQbMulDt61Fd2T3Co", + "refunded": false, + "refunds": { + "object": "list", + "data": [ + ], + "has_more": false, + "total_count": 0, + "url": "/v1/charges/ch_1EW0FmFSbr6xR4YAZyURWxQe/refunds" + }, + "review": null, + "shipping": null, + "source": null, + "source_transfer": null, + "statement_descriptor": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + ], + "has_more": false, + "total_count": 1, + "url": "/v1/charges?payment_intent=pi_1EW0FmFSbr6xR4YAvECSRCv2" + }, + "client_secret": "pi_1EW0FmFSbr6xR4YAvECSRCv2_secret_kUQ34vTWkFRAECbpbswOpAuus", + "confirmation_method": "automatic", + "created": 1556885558, + "currency": "usd", + "customer": "cus_F0026biLhRIcO9", + "description": "Order #34", + "invoice": null, + "last_payment_error": null, + "livemode": false, + "metadata": { + "order_id": "34", + "order_number": "aaefd8ec96095c47ed0c665666c3c768", + "transaction_reference": "84aaac664c7048000146d3a88b5f0081", + "client_ip": "::1" + }, + "next_action": null, + "on_behalf_of": null, + "payment_method": "pm_1EW0FPFSbr6xR4YAZOSMHIOE", + "payment_method_types": [ + "card" + ], + "receipt_email": null, + "review": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null +} \ No newline at end of file diff --git a/tests/Message/PaymentIntents/Mock/UpdatePaymentMethodFailure.txt b/tests/Message/PaymentIntents/Mock/UpdatePaymentMethodFailure.txt new file mode 100644 index 00000000..8834ab54 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/UpdatePaymentMethodFailure.txt @@ -0,0 +1,16 @@ +HTTP/1.1 402 Payment Required +Server: nginx +Date: Tue, 26 Feb 2013 16:17:02 GMT +Content-Type: application/json;charset=utf-8 +Content-Length: 139 +Connection: keep-alive +Access-Control-Max-Age: 300 +Access-Control-Allow-Credentials: true +Cache-Control: no-cache, no-store + +{ + "error": { + "message": "You must save this PaymentMethod to a customer before you can update it.", + "type": "invalid_request_error" + } +} \ No newline at end of file diff --git a/tests/Message/PaymentIntents/Mock/UpdatePaymentMethodSuccess.txt b/tests/Message/PaymentIntents/Mock/UpdatePaymentMethodSuccess.txt new file mode 100644 index 00000000..43ffa236 --- /dev/null +++ b/tests/Message/PaymentIntents/Mock/UpdatePaymentMethodSuccess.txt @@ -0,0 +1,53 @@ +HTTP/1.1 200 OK +Server: nginx +Date: Tue, 26 Feb 2013 16:17:02 GMT +Content-Type: application/json;charset=utf-8 +Content-Length: 139 +Connection: keep-alive +Access-Control-Max-Age: 300 +Access-Control-Allow-Credentials: true +Cache-Control: no-cache, no-store + +{ + "id": "pm_1EUon32Tb35ankTnF6nuoRVE", + "object": "payment_method", + "billing_details": { + "address": { + "city": null, + "country": null, + "line1": null, + "line2": null, + "postal_code": null, + "state": null + }, + "email": null, + "name": null, + "phone": null + }, + "card": { + "brand": "visa", + "checks": { + "address_line1_check": null, + "address_postal_code_check": null, + "cvc_check": null + }, + "country": "US", + "exp_month": 8, + "exp_year": 2020, + "fingerprint": "9OyiQNfcCMaD1b7P", + "funding": "credit", + "generated_from": null, + "last4": "4242", + "three_d_secure_usage": { + "supported": true + }, + "wallet": null + }, + "created": 1556603165, + "customer": "cus_3f2EpMK2kPm90g", + "livemode": false, + "metadata": { + "order_id": "6735" + }, + "type": "card" +} \ No newline at end of file diff --git a/tests/Message/PaymentIntents/PurchaseRequestTest.php b/tests/Message/PaymentIntents/PurchaseRequestTest.php new file mode 100644 index 00000000..09af7fae --- /dev/null +++ b/tests/Message/PaymentIntents/PurchaseRequestTest.php @@ -0,0 +1,60 @@ +request = new PurchaseRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->initialize( + array( + 'amount' => '12.00', + 'currency' => 'USD', + 'paymentMethod' => 'pm_valid_payment_method', + 'description' => 'Order #42', + 'metadata' => array( + 'foo' => 'bar', + ), + 'applicationFee' => '1.00' + ) + ); + } + + public function testGetData() + { + $data = $this->request->getData(); + + $this->assertSame(1200, $data['amount']); + $this->assertSame('usd', $data['currency']); + $this->assertSame('Order #42', $data['description']); + $this->assertSame('automatic', $data['capture_method']); + $this->assertSame('manual', $data['confirmation_method']); + $this->assertSame('pm_valid_payment_method', $data['payment_method']); + $this->assertSame(array('foo' => 'bar'), $data['metadata']); + $this->assertSame(100, $data['application_fee']); + } + + public function testSendSuccessAndRequireConfirmation() + { + $this->setMockHttpResponse('PurchaseSuccess.txt'); + /** @var PaymentIntentsResponse $response */ + $response = $this->request->send(); + + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertFalse($response->requiresConfirmation()); + $this->assertSame('automatic', $response->getCaptureMethod()); + $this->assertSame('pm_1EW0FPFSbr6xR4YAZOSMHIOE', $response->getCardReference()); + $this->assertSame('req_8PDHeZazN2LwML', $response->getRequestId()); + $this->assertSame('cus_F0026biLhRIcO9', $response->getCustomerReference()); + $this->assertNull($response->getMessage()); + } +} diff --git a/tests/Message/PaymentIntents/ResponseTest.php b/tests/Message/PaymentIntents/ResponseTest.php new file mode 100644 index 00000000..73725a9b --- /dev/null +++ b/tests/Message/PaymentIntents/ResponseTest.php @@ -0,0 +1,93 @@ +getMockHttpResponse('AuthorizeSuccess.txt'); + $response = new Response($this->getMockRequest(), (string) $httpResponse->getBody()); + + $this->assertSame('requires_confirmation', $response->getStatus()); + } + + public function testRequiresConfirmation() + { + $httpResponse = $this->getMockHttpResponse('AuthorizeSuccess.txt'); + $response = new Response($this->getMockRequest(), (string) $httpResponse->getBody()); + + $this->assertTrue($response->requiresConfirmation()); + } + + public function testGetCardReference() + { + $httpResponse = $this->getMockHttpResponse('AuthorizeSuccess.txt'); + $response = new Response($this->getMockRequest(), (string) $httpResponse->getBody()); + + $this->assertSame('pm_1Euf5RFSbr6xR4YAwZ5fP28B', $response->getCardReference()); + + $httpResponse = $this->getMockHttpResponse('CreatePaymentMethodSuccess.txt'); + $response = new Response($this->getMockRequest(), (string) $httpResponse->getBody()); + + $this->assertSame('pm_1EUon32Tb35ankTnF6nuoRVE', $response->getCardReference()); + } + + public function testGetCustomerReference() + { + $httpResponse = $this->getMockHttpResponse('AuthorizeSuccess.txt'); + $response = new Response($this->getMockRequest(), (string) $httpResponse->getBody()); + + $this->assertSame('cus_F1UMEEnT2OBgMg', $response->getCustomerReference()); + + $httpResponse = $this->getMockHttpResponse('ConfirmIntent3dsRedirect.txt'); + $response = new Response($this->getMockRequest(), (string) $httpResponse->getBody()); + + $this->assertSame('cus_Q8sHn93nAzgdn1', $response->getCustomerReference()); + } + + public function testGetCaptureMethod() + { + $httpResponse = $this->getMockHttpResponse('AuthorizeSuccess.txt'); + $response = new Response($this->getMockRequest(), (string) $httpResponse->getBody()); + + $this->assertSame('manual', $response->getCaptureMethod()); + + $httpResponse = $this->getMockHttpResponse('PurchaseSuccess.txt'); + $response = new Response($this->getMockRequest(), (string) $httpResponse->getBody()); + + $this->assertSame('automatic', $response->getCaptureMethod()); + } + + public function testGetTransactionReference() + { + $httpResponse = $this->getMockHttpResponse('AuthorizeSuccess.txt'); + $response = new Response($this->getMockRequest(), (string) $httpResponse->getBody()); + + $this->assertNull($response->getTransactionReference()); + + $httpResponse = $this->getMockHttpResponse('PurchaseSuccess.txt'); + $response = new Response($this->getMockRequest(), (string) $httpResponse->getBody()); + + $this->assertSame('ch_1EW0FmFSbr6xR4YAZyURWxQe', $response->getTransactionReference()); + } + + public function testRedirectsAndSuccess() + { + $httpResponse = $this->getMockHttpResponse('ConfirmIntent3dsRedirect.txt'); + $response = new Response($this->getMockRequest(), (string) $httpResponse->getBody()); + + $this->assertFalse($response->isSuccessful()); + $this->assertTrue($response->isRedirect()); + $this->assertSame('https://hooks.stripe.com/3d_secure_2_eap/begin_test/src_1Ev1M5FSbr6xR4YAg5qdBN6B/src_client_secret_FPr4a6wAiVNi6YrnuI7vah6H', $response->getRedirectUrl()); + + $httpResponse = $this->getMockHttpResponse('AuthorizeFailure.txt'); + $response = new Response($this->getMockRequest(), (string) $httpResponse->getBody()); + + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getRedirectUrl()); + } +} diff --git a/tests/Message/PaymentIntents/UpdatePaymentMethodRequestTest.php b/tests/Message/PaymentIntents/UpdatePaymentMethodRequestTest.php new file mode 100644 index 00000000..00526d58 --- /dev/null +++ b/tests/Message/PaymentIntents/UpdatePaymentMethodRequestTest.php @@ -0,0 +1,62 @@ +request = new UpdatePaymentMethodRequest($this->getHttpClient(), $this->getHttpRequest()); + $this->request->setPaymentMethod('pm_some_visa'); + } + + public function testEndpoint() + { + $this->assertSame('https://api.stripe.com/v1/payment_methods/pm_some_visa', $this->request->getEndpoint()); + } + + public function testDataWithCard() + { + $card = $this->getValidCard(); + $metaData = [ + 'meta' => 'data', + 'other' => 'metaData' + ]; + + $this->request->setCard($card); + $this->request->setMetadata($metaData); + $data = $this->request->getData(); + + $this->assertSame($card['billingAddress1'], $data['billing_details']['address']['line1']); + $this->assertSame($card['firstName'] . ' ' . $card['lastName'], $data['billing_details']['name']); + $this->assertSame($card['expiryYear'], $data['card']['exp_year']); + $this->assertSame($metaData, $data['metadata']); + $this->assertArrayNotHasKey('number', $data['card']); + } + + public function testSendSuccess() + { + $this->setMockHttpResponse('UpdatePaymentMethodSuccess.txt'); + $response = $this->request->send(); + + $this->assertTrue($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertSame('pm_1EUon32Tb35ankTnF6nuoRVE', $response->getCardReference()); + $this->assertNull($response->getMessage()); + } + + public function testSendFailure() + { + $this->setMockHttpResponse('UpdatePaymentMethodFailure.txt'); + $response = $this->request->send(); + + $this->assertFalse($response->isSuccessful()); + $this->assertFalse($response->isRedirect()); + $this->assertNull($response->getTransactionReference()); + $this->assertNull($response->getCardReference()); + $this->assertSame('You must save this PaymentMethod to a customer before you can update it.', $response->getMessage()); + } +} diff --git a/tests/PaymentIntentsGatewayTest.php b/tests/PaymentIntentsGatewayTest.php new file mode 100644 index 00000000..26029169 --- /dev/null +++ b/tests/PaymentIntentsGatewayTest.php @@ -0,0 +1,296 @@ +gateway = new PaymentIntentsGateway($this->getHttpClient(), $this->getHttpRequest()); + } + + public function testAuthorize() + { + $request = $this->gateway->authorize(array('amount' => '10.00')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\PaymentIntents\AuthorizeRequest', $request); + $this->assertSame('10.00', $request->getAmount()); + } + + public function testCompleteAuthorize() + { + $request = $this->gateway->completeAuthorize(array('paymentIntentReference' => 'pi_valid_intent')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\PaymentIntents\ConfirmPaymentIntentRequest', $request); + $this->assertSame('pi_valid_intent', $request->getPaymentIntentReference()); + } + + public function testCapture() + { + $request = $this->gateway->capture(array('amount' => '10.00')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\PaymentIntents\CaptureRequest', $request); + $this->assertSame('10.00', $request->getAmount()); + } + + public function testPurchase() + { + $request = $this->gateway->purchase(array('amount' => '10.00')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\PaymentIntents\PurchaseRequest', $request); + $this->assertSame('10.00', $request->getAmount()); + } + + public function testCompletePurchase() + { + $request = $this->gateway->completePurchase(array('paymentIntentReference' => 'pi_valid_intent')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\PaymentIntents\ConfirmPaymentIntentRequest', $request); + $this->assertSame('pi_valid_intent', $request->getPaymentIntentReference()); + } + + public function testConfirmPaymentIntent() + { + $request = $this->gateway->confirm(array('paymentIntentReference' => 'pi_valid_intent')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\PaymentIntents\ConfirmPaymentIntentRequest', $request); + $this->assertSame('pi_valid_intent', $request->getPaymentIntentReference()); + } + + public function testRefund() + { + $request = $this->gateway->refund(array('amount' => '10.00')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\RefundRequest', $request); + $this->assertSame('10.00', $request->getAmount()); + } + + public function testFetchPaymentIntent() + { + $request = $this->gateway->fetchPaymentIntent(array('paymentIntentReference' => 'pi_valid_intent')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\PaymentIntents\FetchPaymentIntentRequest', $request); + $this->assertSame('pi_valid_intent', $request->getPaymentIntentReference()); + } + + public function testVoid() + { + $request = $this->gateway->void(); + + $this->assertInstanceOf('Omnipay\Stripe\Message\VoidRequest', $request); + } + + public function testFetchTransaction() + { + $request = $this->gateway->fetchTransaction(array()); + + $this->assertInstanceOf('Omnipay\Stripe\Message\FetchTransactionRequest', $request); + } + + public function testFetchBalanceTransaction() + { + $request = $this->gateway->fetchBalanceTransaction(array()); + + $this->assertInstanceOf('Omnipay\Stripe\Message\FetchBalanceTransactionRequest', $request); + } + + public function testCreateCard() + { + $request = $this->gateway->createCard(array('description' => 'foo', 'token' => 'tok_real_visa')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\PaymentIntents\CreatePaymentMethodRequest', $request); + $this->assertSame('foo', $request->getDescription()); + $this->assertSame('tok_real_visa', $request->getToken()); + } + + public function testUpdateCard() + { + $request = $this->gateway->updateCard(array('paymentMethod' => 'pm_1EUon32Tb35ankTnF6nuoRVE')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\PaymentIntents\UpdatePaymentMethodRequest', $request); + $this->assertSame('pm_1EUon32Tb35ankTnF6nuoRVE', $request->getPaymentMethod()); + $this->assertSame('pm_1EUon32Tb35ankTnF6nuoRVE', $request->getCardReference()); + } + + public function testDeleteCard() + { + $request = $this->gateway->deleteCard(array('paymentMethod' => 'pm_1EUon32Tb35ankTnF6nuoRVE')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\PaymentIntents\DetachPaymentMethodRequest', $request); + $this->assertSame('pm_1EUon32Tb35ankTnF6nuoRVE', $request->getPaymentMethod()); + $this->assertSame('pm_1EUon32Tb35ankTnF6nuoRVE', $request->getCardReference()); + } + + public function testAttachCard() + { + $request = $this->gateway->attachCard(array('paymentMethod' => 'pm_1EUon32Tb35ankTnF6nuoRVE', 'customerReference' => 'cus_1MZSEtqSghKx99')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\PaymentIntents\AttachPaymentMethodRequest', $request); + $this->assertSame('pm_1EUon32Tb35ankTnF6nuoRVE', $request->getPaymentMethod()); + $this->assertSame('cus_1MZSEtqSghKx99', $request->getCustomerReference()); + } + + public function testCreateCustomer() + { + $request = $this->gateway->createCustomer(array('description' => 'foo@foo.com')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\CreateCustomerRequest', $request); + $this->assertSame('foo@foo.com', $request->getDescription()); + } + + public function testFetchCustomer() + { + $request = $this->gateway->fetchCustomer(array('customerReference' => 'cus_1MZSEtqSghKx99')); + $this->assertInstanceOf('Omnipay\Stripe\Message\FetchCustomerRequest', $request); + $this->assertSame('cus_1MZSEtqSghKx99', $request->getCustomerReference()); + } + + public function testUpdateCustomer() + { + $request = $this->gateway->updateCustomer(array('customerReference' => 'cus_1MZSEtqSghKx99')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\UpdateCustomerRequest', $request); + $this->assertSame('cus_1MZSEtqSghKx99', $request->getCustomerReference()); + } + + public function testDeleteCustomer() + { + $request = $this->gateway->deleteCustomer(array('customerReference' => 'cus_1MZSEtqSghKx99')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\DeleteCustomerRequest', $request); + $this->assertSame('cus_1MZSEtqSghKx99', $request->getCustomerReference()); + } + + public function testCreatePlan() + { + $request = $this->gateway->createPlan(array('id' => 'basic')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\CreatePlanRequest', $request); + $this->assertSame('basic', $request->getId()); + } + + public function testFetchPlan() + { + $request = $this->gateway->fetchPlan(array('id' => 'basic')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\FetchPlanRequest', $request); + $this->assertSame('basic', $request->getId()); + } + + public function testDeletePlan() + { + $request = $this->gateway->deletePlan(array('id' => 'basic')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\DeletePlanRequest', $request); + $this->assertSame('basic', $request->getId()); + } + + public function testListPlans() + { + $request = $this->gateway->listPlans(array()); + + $this->assertInstanceOf('Omnipay\Stripe\Message\ListPlansRequest', $request); + } + + public function testCreateSubscription() + { + $request = $this->gateway->createSubscription(array('plan' => 'basic')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\CreateSubscriptionRequest', $request); + $this->assertSame('basic', $request->getPlan()); + } + + public function testFetchSubscription() + { + $request = $this->gateway->fetchSubscription(array( + 'customerReference' => 'cus_1MZSEtqZghix99', + 'subscriptionReference' => 'sub_1mokfidgjdidf' + )); + + $this->assertInstanceOf('Omnipay\Stripe\Message\FetchSubscriptionRequest', $request); + $this->assertSame('cus_1MZSEtqZghix99', $request->getCustomerReference()); + $this->assertSame('sub_1mokfidgjdidf', $request->getSubscriptionReference()); + } + + public function testUpdateSubscription() + { + $request = $this->gateway->updateSubscription(array('subscriptionReference' => 'sub_1mokfidgjdidf')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\UpdateSubscriptionRequest', $request); + $this->assertSame('sub_1mokfidgjdidf', $request->getSubscriptionReference()); + } + + public function testCancelSubscription() + { + $request = $this->gateway->cancelSubscription(array( + 'customerReference' => 'cus_1MZSEtqZghix99', + 'subscriptionReference' => 'sub_1mokfidgjdidf' + )); + + $this->assertInstanceOf('Omnipay\Stripe\Message\CancelSubscriptionRequest', $request); + $this->assertSame('cus_1MZSEtqZghix99', $request->getCustomerReference()); + $this->assertSame('sub_1mokfidgjdidf', $request->getSubscriptionReference()); + } + + public function testFetchEvent() + { + $request = $this->gateway->fetchEvent(array('eventReference' => 'evt_17X23UCryC4r2g4vdolh6muI')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\FetchEventRequest', $request); + $this->assertSame('evt_17X23UCryC4r2g4vdolh6muI', $request->getEventReference()); + } + + public function testFetchInvoiceLines() + { + $request = $this->gateway->fetchInvoiceLines(array('invoiceReference' => 'in_17ZPbRCryC4r2g4vIdAFxptK')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\FetchInvoiceLinesRequest', $request); + $this->assertSame('in_17ZPbRCryC4r2g4vIdAFxptK', $request->getInvoiceReference()); + } + + public function testFetchInvoice() + { + $request = $this->gateway->fetchInvoice(array('invoiceReference' => 'in_17ZPbRCryC4r2g4vIdAFxptK')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\FetchInvoiceRequest', $request); + $this->assertSame('in_17ZPbRCryC4r2g4vIdAFxptK', $request->getInvoiceReference()); + } + + public function testListInvoices() + { + $request = $this->gateway->listInvoices(array()); + + $this->assertInstanceOf('Omnipay\Stripe\Message\ListInvoicesRequest', $request); + } + + public function testCreateInvoiceItem() + { + $request = $this->gateway->createInvoiceItem(array('invoiceItemReference' => 'ii_17ZPbRCryC4r2g4vIdAFxptK')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\CreateInvoiceItemRequest', $request); + $this->assertSame('ii_17ZPbRCryC4r2g4vIdAFxptK', $request->getInvoiceItemReference()); + } + + public function testFetchInvoiceItem() + { + $request = $this->gateway->fetchInvoiceItem(array('invoiceItemReference' => 'ii_17ZPbRCryC4r2g4vIdAFxptK')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\FetchInvoiceItemRequest', $request); + $this->assertSame('ii_17ZPbRCryC4r2g4vIdAFxptK', $request->getInvoiceItemReference()); + } + + public function testDeleteInvoiceItem() + { + $request = $this->gateway->deleteInvoiceItem(array('invoiceItemReference' => 'ii_17ZPbRCryC4r2g4vIdAFxptK')); + + $this->assertInstanceOf('Omnipay\Stripe\Message\DeleteInvoiceItemRequest', $request); + $this->assertSame('ii_17ZPbRCryC4r2g4vIdAFxptK', $request->getInvoiceItemReference()); + } +}