├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── composer.json ├── dev ├── composer.env.sample ├── docker-compose.yml ├── nginx │ ├── Dockerfile │ ├── bin │ │ └── docker-environment │ └── etc │ │ ├── certs │ │ ├── magento.crt │ │ └── magento.key │ │ └── vhost.conf └── php71 │ ├── Dockerfile │ ├── bin │ ├── magento │ ├── magento-installer │ ├── module-installer │ ├── test-acceptance │ ├── test-integration │ └── test-unit │ ├── docker-entrypoint.sh │ └── etc │ ├── php-fpm.conf │ ├── php-fpm.ini │ └── php-xdebug.ini └── src ├── Block ├── Customer │ └── CardRenderer.php ├── Form.php ├── Info.php └── Payment.php ├── Controller └── ThreeDSecure │ └── Redirect.php ├── Gateway ├── Command │ └── CaptureStrategyCommand.php ├── Config │ ├── CanVoidHandler.php │ └── Config.php ├── Helper │ ├── PriceFormatter.php │ └── SubjectReader.php ├── Http │ ├── Client │ │ ├── AbstractTransaction.php │ │ ├── TransactionRefund.php │ │ ├── TransactionSale.php │ │ ├── TransactionSubmitForSettlement.php │ │ └── TransactionVoid.php │ └── TransferFactory.php ├── Request │ ├── AddressDataBuilder.php │ ├── CaptureDataBuilder.php │ ├── PaymentDataBuilder.php │ ├── PaymentDataBuilder │ │ ├── Admin.php │ │ ├── Vault.php │ │ └── Vault │ │ │ └── Admin.php │ ├── RefundDataBuilder.php │ ├── SettlementDataBuilder.php │ ├── ThreeDSecureBuilder.php │ └── VoidDataBuilder.php ├── Response │ ├── CardDetailsHandler.php │ ├── PaymentDetailsHandler.php │ ├── RefundHandler.php │ ├── TransactionIdHandler.php │ ├── VaultDetailsHandler.php │ └── VoidHandler.php └── Validator │ ├── GeneralResponseValidator.php │ ├── ResponseValidator.php │ └── ResponseValidator │ └── Authorize.php ├── Helper └── CcType.php ├── Model ├── Adapter │ ├── StripeAdapter.php │ └── StripeSearchAdapter.php ├── Adminhtml │ └── Source │ │ ├── Cctype.php │ │ └── PaymentAction.php ├── Helper │ └── OrderPlace.php ├── InstantPurchase │ └── CreditCard │ │ └── TokenFormatter.php └── Ui │ ├── Adminhtml │ └── TokenUiComponentProvider.php │ ├── ConfigProvider.php │ └── TokenUiComponentProvider.php ├── Observer ├── DataAssignObserver.php └── VaultTokenObserver.php ├── Setup ├── InstallData.php └── UpgradeData.php ├── Test ├── Acceptance │ ├── ActionGroup │ │ ├── CompleteGuestAddressFormActionGroup.xml │ │ ├── CompleteStripePaymentFormActionGroup.xml │ │ ├── GetToCheckoutActionGroup.xml │ │ └── ValidateOrderActionGroup.xml │ ├── Data │ │ ├── CardData.xml │ │ └── StripeConfigData.xml │ ├── Metadata │ │ └── stripe_config-meta.xml │ ├── Section │ │ ├── CheckoutPaymentSection.xml │ │ ├── StripeIframeSection.xml │ │ └── ThreeDConfirmationSection.xml │ ├── Test │ │ ├── StorefrontStripeCustomerCheckoutTest.xml │ │ ├── StorefrontStripeCustomerSaveVault3dSecureCheckoutTest.xml │ │ ├── StorefrontStripeCustomerSaveVaultCheckoutTest.xml │ │ ├── StorefrontStripeGuestCheckout3dSecureTest.xml │ │ └── StorefrontStripeGuestCheckoutTest.xml │ └── etc │ │ └── .env.dist ├── Integration │ ├── Model │ │ └── StripeAdapterTest.php │ ├── etc │ │ └── install-config-mysql.php.dist │ └── phpunit.xml.dist └── Unit │ ├── Block │ ├── Customer │ │ └── CardRendererTest.php │ ├── FormTest.php │ ├── InfoTest.php │ └── PaymentTest.php │ ├── Controller │ └── ThreeDSecure │ │ └── RedirectTest.php │ ├── Gateway │ ├── Command │ │ └── CaptureStrategyCommandTest.php │ ├── Config │ │ ├── CanVoidHandlerTest.php │ │ └── ConfigTest.php │ ├── Helper │ │ ├── PriceFormatterTest.php │ │ └── SubjectReaderTest.php │ ├── Http │ │ ├── Client │ │ │ ├── TransactionSaleTest.php │ │ │ └── TransactionSubmitForSettlementTest.php │ │ └── TransferFactoryTest.php │ ├── Request │ │ ├── AddressDataBuilderTest.php │ │ ├── CaptureDataBuilderTest.php │ │ ├── PaymentDataBuilder │ │ │ ├── AdminTest.php │ │ │ ├── Vault │ │ │ │ └── AdminTest.php │ │ │ └── VaultTest.php │ │ ├── PaymentDataBuilderTest.php │ │ ├── RefundDataBuilderTest.php │ │ ├── SettlementDataBuilderTest.php │ │ ├── ThreeDSecureBuilderTest.php │ │ └── VoidDataBuilderTest.php │ ├── Response │ │ ├── CardDetailsHandlerTest.php │ │ ├── PaymentDetailsHandlerTest.php │ │ ├── RefundHandlerTest.php │ │ ├── TransactionHandlerTest.php │ │ ├── VaultDetailsHandlerTest.php │ │ └── VoidHandlerTest.php │ └── Validator │ │ ├── GeneralResponseValidatorTest.php │ │ ├── ResponseValidator │ │ └── AuthorizeTest.php │ │ └── ResponseValidatorTest.php │ ├── Helper │ └── CcTypeTest.php │ ├── Model │ ├── Helper │ │ └── OrderPlaceTest.php │ ├── InstantPurchase │ │ └── CreditCard │ │ │ └── TokenFormatterTest.php │ └── Ui │ │ ├── Adminhtml │ │ └── TokenUiComponentProviderTest.php │ │ ├── ConfigProviderTest.php │ │ └── TokenUiComponentProviderTest.php │ ├── Observer │ └── DataAssignObserverTest.php │ └── phpunit.xml.dist ├── etc ├── adminhtml │ ├── di.xml │ └── system.xml ├── config.xml ├── di.xml ├── events.xml ├── frontend │ ├── di.xml │ └── routes.xml └── module.xml ├── registration.php └── view ├── adminhtml ├── layout │ ├── sales_order_create_index.xml │ └── sales_order_create_load_block_billing_method.xml ├── templates │ ├── form │ │ ├── cc.phtml │ │ └── vault.phtml │ └── payment │ │ └── script.phtml └── web │ └── js │ ├── stripe.js │ └── vault.js └── frontend ├── layout ├── checkout_index_index.xml └── vault_cards_listaction.xml └── web ├── js ├── action │ └── save-payment-information.js ├── model │ └── save-payment-information.js └── view │ └── payment │ ├── method-renderer │ ├── pmclain_stripe.js │ └── vault.js │ └── pmclain_stripe.js └── template └── payment └── form.html /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.idea 3 | 4 | /dev/magento 5 | /dev/composer.env -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | services: 3 | - docker 4 | language: php 5 | php: 6 | - 7.1 7 | matrix: 8 | include: 9 | - env: 10 | - MAGENTO_VERSION=~2.2 11 | - TEST_SUITE=unit 12 | - env: 13 | - MAGENTO_VERSION=~2.2 14 | - TEST_SUITE=integration 15 | - env: 16 | - MAGENTO_VERSION=~2.2 17 | - TEST_SUITE=acceptance 18 | cache: 19 | directories: 20 | - $HOME/.composer/cache 21 | install: 22 | - mkdir -p build/logs && cd build && composer init --no-interaction && composer require php-coveralls/php-coveralls --no-interaction && cd .. 23 | before_script: 24 | - echo "COMPOSER_MAGENTO_USERNAME=$COMPOSER_MAGENTO_USERNAME" >> dev/composer.env 25 | - echo "COMPOSER_MAGENTO_PASSWORD=$COMPOSER_MAGENTO_PASSWORD" >> dev/composer.env 26 | - echo "COMPOSER_GITHUB_TOKEN=$COMPOSER_GITHUB_TOKEN" >> dev/composer.env 27 | - sed -E -i "s/MAGENTO_VERSION=.*/MAGENTO_VERSION=${MAGENTO_VERSION}/" dev/docker-compose.yml 28 | - docker-compose -f dev/docker-compose.yml up -d 29 | - docker-compose -f dev/docker-compose.yml exec app module-installer 30 | script: 31 | - docker-compose -f dev/docker-compose.yml exec app test-${TEST_SUITE} 32 | after_success: 33 | - cp dev/magento/dev/tests/${TEST_SUITE}/coverage/clover.xml build/logs/clover.xml 34 | - sed -E -i "s/\/module/\./" build/logs/clover.xml 35 | - travis_retry php build/vendor/bin/php-coveralls -v 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Magento 2 Stripe Integration 2 | 3 | [![Build Status](https://travis-ci.org/pmclain/module-stripe.svg?branch=master)](https://travis-ci.org/pmclain/module-stripe) 4 | [![Coverage Status](https://coveralls.io/repos/github/pmclain/module-stripe/badge.svg?branch=master)](https://coveralls.io/github/pmclain/module-stripe?branch=master) 5 | [![Latest Stable Version](https://poser.pugx.org/pmclain/module-stripe/v/stable)](https://packagist.org/packages/pmclain/module-stripe) 6 | [![Total Downloads](https://poser.pugx.org/pmclain/module-stripe/downloads)](https://packagist.org/packages/pmclain/module-stripe) 7 | [![License](https://poser.pugx.org/pmclain/module-stripe/license)](https://packagist.org/packages/pmclain/module-stripe) 8 | 9 | Accept credit card payments through the Stripe payment gateway. 10 | 11 | * Supports Magento Instant Purchase for One Click Checkout 12 | * Securely accept customer payments using the Stripe.js tokenization when 13 | collecting all payments. 14 | * Provide customers option of storing payment information for future 15 | transactions. 16 | * Stored customer card information can be used for orders created in the 17 | frontend or backend. 18 | * Stored cards deleted by customer in Magento are also removed from the 19 | corresponding Stripe customer profile. 20 | * New payments can be authorize or authorize and capture. 21 | * Authorized payments can be captured online during invoice creation. 22 | * Full and partial refund support when creating credit memos. 23 | * 3D Secure support for one-time and vault payments 24 | 25 | ## Installation 26 | #### Composer 27 | In your Magento 2 root directory run 28 | `composer require pmclain/module-stripe` 29 | `bin/magento setup:upgrade` 30 | 31 | ## Magento Version Requirements 32 | | Release | Magento Version | 33 | | ------- | --------------- | 34 | | 2.1.x | >=2.2.5 | 35 | | 2.0.x | 2.2.0-2.2.4 | 36 | | 1.x.x   | 2.1.x           | 37 | | None | 2.0.x | 38 | 39 | ## Configuration 40 | The configuration can be found in the Magento 2 admin panel under 41 | Store->Configuration->Sales->Payment Methods->Stripe 42 | 43 | ## Feature Roadmap 44 | There is no ETA for implementation, but here is the list in order of priority. 45 | 1. Multi-shipping address support 46 | 2. Stripe Radar 47 | 48 | ## Testing and Local Development 49 | **WARNING** 50 | The docker setup included is intended for local development only. 51 | 52 | ### Local Development 53 | `cd ./dev` 54 | `docker-compose up -d` 55 | `docker-compose exec app module-installer` 56 | `docker-compose exec app magento-installer` 57 | 58 | Create the host entry `127.0.0.1 stripe.docker` 59 | 60 | ### Execute Tests 61 | * Setup 62 | `docker-compose -f dev/docker-compose.yml up -d` 63 | `docker-compose -f dev/docker-compose.yml exec app module-installer` 64 | * Unit - `docker-compose -f dev/docker-compose.yml exec app test-unit` 65 | * Integration - `docker-compose -f dev/docker-compose.yml exec app test-integration` 66 | * Acceptance - `docker-compose -f dev/docker-compose.yml exec app test-acceptance` 67 | 68 | ## License 69 | Open Software License v3.0 70 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pmclain/module-stripe", 3 | "description": "Stripe Payments for Magento 2", 4 | "type": "magento2-module", 5 | "license": "OSL-3.0", 6 | "require": { 7 | "php": "~7.0.0||~7.1.0||~7.2.0", 8 | "magento/framework": "~101.0.5||~100.3.0-dev", 9 | "stripe/stripe-php": "~6.7.0" 10 | }, 11 | "autoload": { 12 | "files": [ 13 | "src/registration.php" 14 | ], 15 | "psr-4": { 16 | "Pmclain\\Stripe\\": "src/" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /dev/composer.env.sample: -------------------------------------------------------------------------------- 1 | COMPOSER_MAGENTO_USERNAME=0000 2 | COMPOSER_MAGENTO_PASSWORD=0000 3 | COMPOSER_GITHUB_TOKEN=0000 -------------------------------------------------------------------------------- /dev/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | web: 4 | image: dfaarc44/m2-nginx 5 | ports: 6 | - "80:80" 7 | - "443:443" 8 | links: 9 | - app 10 | networks: 11 | default: 12 | aliases: 13 | - stripe.docker 14 | volumes: 15 | - ./magento:/var/www/magento 16 | environment: 17 | - VIRTUAL_HOST=stripe.docker 18 | 19 | app: 20 | image: dfaarc44/m2-stripe-app:php71 21 | links: 22 | - db 23 | - redis 24 | - amqp 25 | - mailcatcher 26 | - stripemock 27 | volumes: 28 | - ~/.composer/cache:/root/.composer/cache 29 | - ./magento:/var/www/magento:cached 30 | - ..:/module 31 | env_file: 32 | - ./composer.env 33 | environment: 34 | - PHP_IDE_CONFIG=serverName=stripe.docker 35 | - XDEBUG_ENABLE=true 36 | - MAGENTO_RUN_MODE=developer 37 | - MAGENTO_VERSION=~2.2 38 | - MAGENTO_URL=https://stripe.docker 39 | 40 | db: 41 | image: mariadb:10 42 | user: mysql 43 | ports: 44 | - "9306:3306" 45 | volumes: 46 | - dbdata:/var/lib/mysql 47 | environment: 48 | - MYSQL_ROOT_PASSWORD=magento 49 | - MYSQL_DATABASE=magento 50 | - MYSQL_USER=magento 51 | - MYSQL_PASSWORD=magento 52 | 53 | redis: 54 | image: redis 55 | ports: 56 | - 6379 57 | 58 | amqp: 59 | image: rabbitmq:3-management 60 | ports: 61 | - "15672:15672" 62 | environment: 63 | - RABBITMQ_DEFAULT_USER=guest 64 | - RABBITMQ_DEFAULT_PASSWORD=guest 65 | 66 | mailcatcher: 67 | image: helder/mailcatcher 68 | ports: 69 | - "1080:80" 70 | 71 | chrome: 72 | image: selenium/standalone-chrome-debug 73 | ports: 74 | - "49338:5900" 75 | 76 | stripemock: 77 | image: stripemock/stripe-mock 78 | ports: 79 | - 12111 80 | - 12112 81 | 82 | volumes: 83 | dbdata: 84 | 85 | networks: 86 | default: -------------------------------------------------------------------------------- /dev/nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:1.9 2 | 3 | LABEL MAINTAINER="Patrick McLain " 4 | 5 | ADD etc/vhost.conf /etc/nginx/conf.d/default.conf 6 | COPY etc/certs/ /etc/nginx/ssl/ 7 | ADD bin/* /usr/local/bin/ 8 | 9 | EXPOSE 443 10 | 11 | ENV FPM_HOST app 12 | ENV FPM_PORT 9000 13 | ENV MAGENTO_ROOT /var/www/magento 14 | ENV MAGENTO_RUN_MODE developer 15 | ENV DEBUG false 16 | 17 | RUN ["sed", "-i", "s/user nginx;/user root;/", "/etc/nginx/nginx.conf"] 18 | 19 | RUN ["chmod", "+x", "/usr/local/bin/docker-environment"] 20 | 21 | ENTRYPOINT ["/usr/local/bin/docker-environment"] 22 | CMD ["nginx", "-g", "daemon off;"] 23 | -------------------------------------------------------------------------------- /dev/nginx/bin/docker-environment: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ "$DEBUG" = "true" ] && set -x 4 | 5 | VHOST_FILE="/etc/nginx/conf.d/default.conf" 6 | 7 | [ ! -z "${FPM_HOST}" ] && sed -i "s/!FPM_HOST!/${FPM_HOST}/" $VHOST_FILE 8 | [ ! -z "${FPM_PORT}" ] && sed -i "s/!FPM_PORT!/${FPM_PORT}/" $VHOST_FILE 9 | [ ! -z "${MAGENTO_ROOT}" ] && sed -i "s#!MAGENTO_ROOT!#${MAGENTO_ROOT}#" $VHOST_FILE 10 | [ ! -z "${MAGENTO_RUN_MODE}" ] && sed -i "s/!MAGENTO_RUN_MODE!/${MAGENTO_RUN_MODE}/" $VHOST_FILE 11 | [ ! -z "${UPLOAD_MAX_FILESIZE}" ] && sed -i "s/!UPLOAD_MAX_FILESIZE!/${UPLOAD_MAX_FILESIZE}/" $VHOST_FILE 12 | 13 | # Check if the nginx syntax is fine, then launch. 14 | nginx -t 15 | 16 | exec "$@" -------------------------------------------------------------------------------- /dev/nginx/etc/certs/magento.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDdDCCAlwCCQCkL06EvsPP2TANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJH 3 | QjERMA8GA1UECBMIU29tZXJzZXQxDTALBgNVBAcTBEJhdGgxEDAOBgNVBAoTB01l 4 | YW5iZWUxFDASBgNVBAMTC21hZ2VudG8uZGV2MSMwIQYJKoZIhvcNAQkBFhRzeXNh 5 | ZG1pbkBleGFtcGxlLmNvbTAeFw0xNzA2MjgxMjEyMTZaFw0yNzA2MjYxMjEyMTZa 6 | MHwxCzAJBgNVBAYTAkdCMREwDwYDVQQIEwhTb21lcnNldDENMAsGA1UEBxMEQmF0 7 | aDEQMA4GA1UEChMHTWVhbmJlZTEUMBIGA1UEAxMLbWFnZW50by5kZXYxIzAhBgkq 8 | hkiG9w0BCQEWFHN5c2FkbWluQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEF 9 | AAOCAQ8AMIIBCgKCAQEA71Ar7riah4gVBY6AisU76n1qYNDhnKLZ6OAd2I+3ll+U 10 | zQPzb2B+Mn32zo1WURGmBODUMfvAsfPaW/XWODfaAzi+0x3+K/5h5t28Twkc3x4J 11 | 5jFuJGhTqez30lxrG6KgAsKo61NL80Ey6wgC/G+EOOL/xrwOKi8veSKPcFWQCI5P 12 | Ctjhb1uW5n5UvelnZ4P8Q+o4gzjPGW0UgtZqdOBD9gUSF8gRtxwyqoJldyY+YWpv 13 | eQGmlj6bqMPR27EVPjmtXTdY7SASt8FwZviLlIb3d0MegEJOasAbbRqwKb8Frnuu 14 | xUG17ga0WoK939uAnL6F7dTfDBusE4AUfuHrmSzp2wIDAQABMA0GCSqGSIb3DQEB 15 | CwUAA4IBAQDM4Et6nCcAISR+J4rA4iF8mLi+1dj94KHcdmanm7Y06wFzt7g1Lf5u 16 | DjHbVzqqLNCNGIsxOA5f2ERQ2vqXR+0PkB85Yhgr2xyFnmpgo8qoroHnCEvdVPi0 17 | a96nb7LmhknC2zWHAufXy1vyNRWuGLHIUUw5xnTUhJkhybJiT/68F0uK/qmwbSGb 18 | bGKsR8Z5UeE7OPT+OEplpIVBo55ktQ4ehAxB3FCa8kZdpYNASsfcyHOYTVDXMlVL 19 | OT3VHhx7i0qh1mFm+SLST82Noq0bhbNRnd2HlkUrsSX8LAeI4YvSnvnbxs//Bm0d 20 | 9BocWjDXr12xHdbS7SMoZPgBZ9Bn9koV 21 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /dev/nginx/etc/certs/magento.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpQIBAAKCAQEA71Ar7riah4gVBY6AisU76n1qYNDhnKLZ6OAd2I+3ll+UzQPz 3 | b2B+Mn32zo1WURGmBODUMfvAsfPaW/XWODfaAzi+0x3+K/5h5t28Twkc3x4J5jFu 4 | JGhTqez30lxrG6KgAsKo61NL80Ey6wgC/G+EOOL/xrwOKi8veSKPcFWQCI5PCtjh 5 | b1uW5n5UvelnZ4P8Q+o4gzjPGW0UgtZqdOBD9gUSF8gRtxwyqoJldyY+YWpveQGm 6 | lj6bqMPR27EVPjmtXTdY7SASt8FwZviLlIb3d0MegEJOasAbbRqwKb8FrnuuxUG1 7 | 7ga0WoK939uAnL6F7dTfDBusE4AUfuHrmSzp2wIDAQABAoIBACl/GV8Xm5QMwLhp 8 | 8Vgewzjx7lRDZBupEWgUFJjMsuTcRg0WtkuFy9wtg3Jlh6YfDU6jPag9Izi4NBDm 9 | G/M7nA4a9Nvew4gVYByMLm72AY+ewdCsmZCulnNMp9xOMjRkiqJv5qKHmw/fKlke 10 | 1oW3QJIsqnVnfn1KGU1D9ONhsswIq0x8u3NEt0Fc3zRjVm6dcXef6kNBZJQNynFG 11 | BbDfV0qkuiTmabvh04huhldtHYZmHXAHeeQ9k0SRkn9gVdSqjMe+DQ5odjaukotb 12 | P1qnG94AdkXuVDGNXFoQ8rNLZPXQ9UO/P81pN6og728u+OuwaSwYgJhia4j88zg/ 13 | Ffptg6ECgYEA+aRh1iQFHGj5eT/dijgghnkK2fkoZlKGazeDdqME9ASpZPuLiPI0 14 | 0ng+BEWA2ejLM/B0UuBm/VWy9cwT7F4d5ByCvrpclYA0Tn7d94K6YP0cwBYvHa54 15 | j6fkKgy/R1BjKCD2AKI2g0Hgh3QzgrgPwMdZcjEi4eWbLx9s6ocCLLcCgYEA9Why 16 | XB9FTQdK/ptGSAKye+VVXqXqYxFHHKes55b+ACbK2mYF9Xqp7z0fu56ZqCdxGbG2 17 | GmhFM8RnebsHGc38761+VrI73GQ6S2dMKt6PzCg7t+3NCaF7Z+t65kEV55w6Vmri 18 | eIw34hXTpbPemHXomcvifpY9ootqnP0BhjfYD/0CgYEArBZV3yEbaNcwShXtaM+C 19 | FFCyW0n3QHnY8WXmOMztqCzifJsuN+wG36NF1Pn4db6U/SvfdBX+yNnfsLLKdSD3 20 | 5/yDYGjlU6V56TZpWqqCQkOZIwzn08UmlJi+nwIEhWtzvwDhs9QeUeMCnT1MGOs6 21 | 6MBC94XJrwDxNc2q7gy9QgcCgYEAnBHrwNiGS0GbGScI4F0Ow6qKy2G7GXvwfLHK 22 | TZKCQPhqw9Bkc8Sp9CMsXja0Q/Opgwy44jxz3kNHB2zBTFDrTkZI9bvuQ/Bd/nxY 23 | PV9DljP0HroWTsyq3eEtTOgRlTWPCEx7cOzD0X3OFzC4HL/HyJ+YkKbd1dTSXbqt 24 | 0H0NZMUCgYEA0Fdu0oZMMDDWFFEcRY5PVenxuj59cl6gARB86e5p3clIGwTx5/5C 25 | FJzp0zdfb9vE/cTlV3mKSFUskSUTFHaHjI1w3oRD/oDMkgImRpDvqye0PBpiSyRE 26 | Cz4N7ikKJRzxABkHtCqEG+VA/ah2obIpbzYSfGTAKlS/6u7FBgLSmn8= 27 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /dev/php71/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:7.1-fpm 2 | 3 | LABEL MAINTAINER="Patrick McLain " 4 | 5 | # Install dependencies 6 | RUN apt-get update \ 7 | && apt-get install -y \ 8 | libfreetype6-dev \ 9 | libicu-dev \ 10 | libjpeg62-turbo-dev \ 11 | libmcrypt-dev \ 12 | libpng-dev \ 13 | libxslt1-dev \ 14 | openssl \ 15 | sudo \ 16 | cron \ 17 | rsyslog \ 18 | mysql-client \ 19 | git \ 20 | ssmtp \ 21 | unzip \ 22 | procps 23 | 24 | # Configure the gd library 25 | RUN docker-php-ext-configure \ 26 | gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ 27 | 28 | # Install required PHP extensions 29 | 30 | RUN docker-php-ext-install \ 31 | dom \ 32 | gd \ 33 | intl \ 34 | mbstring \ 35 | pdo_mysql \ 36 | xsl \ 37 | zip \ 38 | soap \ 39 | bcmath \ 40 | mcrypt 41 | 42 | RUN pecl install -o -f xdebug 43 | 44 | VOLUME /root/.composer/cache 45 | RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer 46 | 47 | ENV PHP_MEMORY_LIMIT 756M 48 | ENV XDEBUG_REMOTE_HOST docker.for.mac.localhost 49 | ENV MAGENTO_ROOT /var/www/magento 50 | ENV MAGENTO_CLEAN_DATABASE 0 51 | ENV XDEBUG_ENABLE false 52 | 53 | ADD etc/php-fpm.ini /usr/local/etc/php/conf.d/zz-magento.ini 54 | ADD etc/php-xdebug.ini /usr/local/etc/php/conf.d/zz-xdebug.ini 55 | RUN echo "sendmail_path = /usr/sbin/ssmtp -t" > /usr/local/etc/php/conf.d/zz-sendmail.ini 56 | RUN echo "mailhub=mailcatcher:25\nUseTLS=NO\nFromLineOverride=YES" > /etc/ssmtp/ssmtp.conf 57 | 58 | ADD bin/* /usr/local/bin/ 59 | 60 | RUN ["chmod", "+x", "/usr/local/bin/magento"] 61 | RUN ["chmod", "+x", "/usr/local/bin/magento-installer"] 62 | RUN ["chmod", "+x", "/usr/local/bin/module-installer"] 63 | RUN ["chmod", "+x", "/usr/local/bin/test-unit"] 64 | RUN ["chmod", "+x", "/usr/local/bin/test-integration"] 65 | RUN ["chmod", "+x", "/usr/local/bin/test-acceptance"] 66 | 67 | ADD docker-entrypoint.sh /docker-entrypoint.sh 68 | 69 | RUN ["chmod", "+x", "/docker-entrypoint.sh"] 70 | 71 | ENTRYPOINT ["/docker-entrypoint.sh"] 72 | 73 | ADD etc/php-fpm.conf /usr/local/etc/ 74 | 75 | CMD ["php-fpm", "-F", "-R"] -------------------------------------------------------------------------------- /dev/php71/bin/magento: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MAGENTO_COMMAND="php $MAGENTO_ROOT/bin/magento" 4 | 5 | $MAGENTO_COMMAND "$@" 6 | -------------------------------------------------------------------------------- /dev/php71/bin/magento-installer: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MAGENTO_COMMAND="php $MAGENTO_ROOT/bin/magento" 4 | INSTALL_COMMAND="setup:install \ 5 | --admin-firstname admin \ 6 | --admin-lastname user \ 7 | --admin-email admin@mage2.docker \ 8 | --admin-user admin \ 9 | --admin-password passwd123 \ 10 | --base-url $MAGENTO_URL \ 11 | --backend-frontname admin \ 12 | --db-host db \ 13 | --db-name magento \ 14 | --db-user magento \ 15 | --db-password magento \ 16 | --use-rewrites 1 \ 17 | --use-secure 1 \ 18 | --base-url-secure $MAGENTO_URL \ 19 | --use-secure-admin 1 \ 20 | --admin-use-security-key 0 \ 21 | --session-save redis \ 22 | --session-save-redis-host redis \ 23 | --session-save-redis-db 0 \ 24 | --admin-use-security-key 0" 25 | 26 | $MAGENTO_COMMAND $INSTALL_COMMAND 27 | -------------------------------------------------------------------------------- /dev/php71/bin/module-installer: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ ! -f "${MAGENTO_ROOT}/index.php" ] && \ 4 | echo "Creating Magento composer project" && \ 5 | composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition:$MAGENTO_VERSION $MAGENTO_ROOT 6 | 7 | composer config minimum-stability dev -d $MAGENTO_ROOT 8 | composer config repositories.stripe path /module -d $MAGENTO_ROOT 9 | composer require pmclain/module-stripe:@dev -d $MAGENTO_ROOT 10 | -------------------------------------------------------------------------------- /dev/php71/bin/test-acceptance: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $MAGENTO_ROOT 4 | 5 | [ -f "${MAGENTO_ROOT}/app/etc/env.php" ] && rm ${MAGENTO_ROOT}/app/etc/env.php 6 | 7 | # Prevent RSA check when installing MFTF :( 8 | mkdir -p ~/.ssh 9 | echo -e "Host *\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config 10 | 11 | magento setup:install \ 12 | --admin-firstname admin \ 13 | --admin-lastname user \ 14 | --admin-email admin@mage2.docker \ 15 | --admin-user admin \ 16 | --admin-password passwd123 \ 17 | --base-url http://stripe.docker/ \ 18 | --backend-frontname admin \ 19 | --db-host db \ 20 | --db-name magento \ 21 | --db-user magento \ 22 | --db-password magento \ 23 | --use-rewrites 1 \ 24 | --use-secure 0 \ 25 | --use-secure-admin 0 \ 26 | --admin-use-security-key 0 \ 27 | --session-save redis \ 28 | --session-save-redis-host redis \ 29 | --session-save-redis-db 0 \ 30 | --admin-use-security-key 0 31 | 32 | php bin/magento deploy:mode:set production 33 | 34 | cp vendor/pmclain/module-stripe/src/Test/Acceptance/etc/.env.dist dev/tests/acceptance/.env 35 | 36 | cd dev/tests/acceptance 37 | composer install 38 | 39 | vendor/bin/robo build:project 40 | vendor/bin/robo generate:tests 41 | vendor/bin/codecept run functional --group pmclain_stripe 42 | -------------------------------------------------------------------------------- /dev/php71/bin/test-integration: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $MAGENTO_ROOT 4 | 5 | cp vendor/pmclain/module-stripe/src/Test/Integration/phpunit.xml.dist dev/tests/integration/phpunit.xml 6 | cp vendor/pmclain/module-stripe/src/Test/Integration/etc/install-config-mysql.php.dist dev/tests/integration/etc/install-config-mysql.php 7 | 8 | cd dev/tests/integration 9 | 10 | ../../../vendor/bin/phpunit -------------------------------------------------------------------------------- /dev/php71/bin/test-unit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $MAGENTO_ROOT 4 | 5 | cp vendor/pmclain/module-stripe/src/Test/Unit/phpunit.xml.dist dev/tests/unit/phpunit.xml 6 | cd dev/tests/unit 7 | 8 | ../../../vendor/bin/phpunit -------------------------------------------------------------------------------- /dev/php71/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Setup Magento cron 4 | echo "* * * * * www-data /usr/local/bin/php ${MAGENTO_ROOT}/bin/magento cron:run | grep -v \"Ran jobs by schedule\" >> ${MAGENTO_ROOT}/var/log/magento.cron.log" > /etc/cron.d/magento 5 | echo "* * * * * www-data /usr/local/bin/php ${MAGENTO_ROOT}/update/cron.php >> ${MAGENTO_ROOT}/var/log/update.cron.log" >> /etc/cron.d/magento 6 | echo "* * * * * www-data /usr/local/bin/php ${MAGENTO_ROOT}/bin/magento setup:cron:run >> ${MAGENTO_ROOT}/var/log/setup.cron.log" >> /etc/cron.d/magento 7 | 8 | # Substitute in php.ini values 9 | [ ! -z "${PHP_MEMORY_LIMIT}" ] && sed -i "s/!PHP_MEMORY_LIMIT!/${PHP_MEMORY_LIMIT}/" /usr/local/etc/php/conf.d/zz-magento.ini 10 | [ ! -z "${XDEBUG_REMOTE_HOST}" ] && sed -i "s/!XDEBUG_REMOTE_HOST!/${XDEBUG_REMOTE_HOST}/" /usr/local/etc/php/conf.d/zz-xdebug.ini 11 | 12 | # Configure PHP-FPM 13 | [ ! -z "${MAGENTO_RUN_MODE}" ] && sed -i "s/!MAGENTO_RUN_MODE!/${MAGENTO_RUN_MODE}/" /usr/local/etc/php-fpm.conf 14 | 15 | [ "$XDEBUG_ENABLE" = "true" ] && \ 16 | docker-php-ext-enable xdebug && \ 17 | echo "Xdebug is enabled" 18 | 19 | [ ! -z "${COMPOSER_MAGENTO_USERNAME}" ] && \ 20 | composer config --global http-basic.repo.magento.com \ 21 | $COMPOSER_MAGENTO_USERNAME $COMPOSER_MAGENTO_PASSWORD 22 | 23 | [ ! -z "${COMPOSER_GITHUB_TOKEN}" ] && \ 24 | composer config -g github-oauth.github.com $COMPOSER_GITHUB_TOKEN 25 | 26 | exec "$@" 27 | -------------------------------------------------------------------------------- /dev/php71/etc/php-fpm.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | 3 | error_log = /proc/self/fd/2 4 | daemonize = no 5 | 6 | [www] 7 | 8 | ; if we send this to /proc/self/fd/1, it never appears 9 | access.log = /proc/self/fd/2 10 | 11 | user = root 12 | group = root 13 | 14 | listen = [::]:9000 15 | 16 | pm = dynamic 17 | pm.max_children = 10 18 | pm.start_servers = 4 19 | pm.min_spare_servers = 2 20 | pm.max_spare_servers = 6 21 | 22 | env[MAGE_MODE] = !MAGENTO_RUN_MODE!; # Variable: MAGENTO_RUN_MODE 23 | 24 | clear_env = no 25 | 26 | ; Ensure worker stdout and stderr are sent to the main error log. 27 | catch_workers_output = yes -------------------------------------------------------------------------------- /dev/php71/etc/php-fpm.ini: -------------------------------------------------------------------------------- 1 | 2 | memory_limit = !PHP_MEMORY_LIMIT! -------------------------------------------------------------------------------- /dev/php71/etc/php-xdebug.ini: -------------------------------------------------------------------------------- 1 | xdebug.remote_enable = 1 2 | xdebug.remote_autostart = 1 3 | xdebug.remote_host = !XDEBUG_REMOTE_HOST! 4 | xdebug.remote_port = 9100 5 | 6 | xdebug.scream = 0 7 | xdebug.show_local_vars = 1 8 | 9 | ; xdebug.remote_log = /var/www/magento/xdebug.log 10 | 11 | xdebug.idekey = PHPSTORM -------------------------------------------------------------------------------- /src/Block/Customer/CardRenderer.php: -------------------------------------------------------------------------------- 1 | getPaymentMethodCode() === ConfigProvider::CODE; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getNumberLast4Digits() 40 | { 41 | return $this->getTokenDetails()['maskedCC']; 42 | } 43 | 44 | /** 45 | * @return string 46 | */ 47 | public function getExpDate() 48 | { 49 | return $this->getTokenDetails()['expirationDate']; 50 | } 51 | 52 | /** 53 | * @return string 54 | */ 55 | public function getIconUrl() 56 | { 57 | return $this->getIconForType($this->getTokenDetails()['type'])['url']; 58 | } 59 | 60 | /** 61 | * @return int 62 | */ 63 | public function getIconHeight() 64 | { 65 | return $this->getIconForType($this->getTokenDetails()['type'])['height']; 66 | } 67 | 68 | /** 69 | * @return int 70 | */ 71 | public function getIconWidth() 72 | { 73 | return $this->getIconForType($this->getTokenDetails()['type'])['width']; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Block/Form.php: -------------------------------------------------------------------------------- 1 | gatewayConfig = $gatewayConfig; 52 | $this->paymentDataHelper = $helper; 53 | } 54 | 55 | /** 56 | * @return bool 57 | */ 58 | public function useCcv() 59 | { 60 | return $this->gatewayConfig->isCcvEnabled(); 61 | } 62 | 63 | /** 64 | * Check if vault enabled 65 | * @return bool 66 | */ 67 | public function isVaultEnabled() 68 | { 69 | $storeId = $this->_storeManager->getStore()->getId(); 70 | $vaultPayment = $this->getVaultPayment(); 71 | return $vaultPayment->isActive($storeId); 72 | } 73 | 74 | /** 75 | * @return VaultPaymentInterface 76 | */ 77 | private function getVaultPayment() 78 | { 79 | return $this->paymentDataHelper->getMethodInstance(ConfigProvider::CC_VAULT_CODE); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Block/Payment.php: -------------------------------------------------------------------------------- 1 | config = $config; 47 | } 48 | 49 | /** 50 | * @return string 51 | */ 52 | public function getPaymentConfig() 53 | { 54 | $payment = $this->config->getConfig()['payment']; 55 | $config = $payment[$this->getCode()]; 56 | $config['code'] = $this->getCode(); 57 | return json_encode($config, JSON_UNESCAPED_SLASHES); 58 | } 59 | 60 | /** 61 | * @return string 62 | */ 63 | public function getCode() 64 | { 65 | return ConfigProvider::CODE; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Controller/ThreeDSecure/Redirect.php: -------------------------------------------------------------------------------- 1 | session = $session; 44 | $this->orderPlace = $orderPlace; 45 | } 46 | 47 | public function execute() 48 | { 49 | $resultRedirect = $this->resultRedirectFactory->create(); 50 | 51 | $quote = $this->session->getQuote(); 52 | 53 | try { 54 | $this->validateQuote($quote); 55 | 56 | $this->orderPlace->execute( 57 | $quote, 58 | $this->getRequest()->getParam('source'), 59 | $this->getRequest()->getParam('client_secret') 60 | ); 61 | 62 | $resultRedirect->setPath('checkout/onepage/success', ['_secure' => true]); 63 | } catch (\InvalidArgumentException $e) { 64 | $this->messageManager->addErrorMessage($e->getMessage()); 65 | $resultRedirect->setPath('checkout/cart', ['_secure' => true]); 66 | } catch (LocalizedException $e) { 67 | $this->messageManager->addErrorMessage($e->getMessage()); 68 | $resultRedirect->setPath('checkout/cart', ['_secure' => true]); 69 | } 70 | 71 | return $resultRedirect; 72 | } 73 | 74 | /** 75 | * @param \Magento\Quote\Model\Quote $quote 76 | */ 77 | private function validateQuote($quote) 78 | { 79 | if (!$quote || !$quote->getItemsCount()) { 80 | throw new \InvalidArgumentException(__('We can\'t initialize checkout.')); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/Gateway/Config/CanVoidHandler.php: -------------------------------------------------------------------------------- 1 | subjectReader = $subjectReader; 38 | } 39 | 40 | /** 41 | * @param array $subject 42 | * @param null $storeId 43 | * @return bool 44 | */ 45 | public function handle(array $subject, $storeId = null) 46 | { 47 | $paymentDataObject = $this->subjectReader->readPayment($subject); 48 | $payment = $paymentDataObject->getPayment(); 49 | 50 | return $payment instanceof Payment && !(bool)$payment->getAmountPaid(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Gateway/Helper/PriceFormatter.php: -------------------------------------------------------------------------------- 1 | config = $config; 36 | } 37 | 38 | /** 39 | * @param string $price 40 | * @return string 41 | */ 42 | public function formatPrice($price) 43 | { 44 | $price = sprintf('%.' . ($this->isZeroDecimalCurrency() ? '0' : '2') . 'F', $price); 45 | 46 | return str_replace('.', '', $price); 47 | } 48 | 49 | /** 50 | * @return bool 51 | */ 52 | private function isZeroDecimalCurrency() 53 | { 54 | return in_array($this->config->getCurrency(), $this->getZeroDecimalCurrencies(), true); 55 | } 56 | 57 | /** 58 | * @return array 59 | */ 60 | private function getZeroDecimalCurrencies() 61 | { 62 | return [ 63 | 'BIF', 64 | 'CLP', 65 | 'DJF', 66 | 'GNF', 67 | 'JPY', 68 | 'KMF', 69 | 'KRW', 70 | 'MGA', 71 | 'PYG', 72 | 'RWF', 73 | 'UGX', 74 | 'VND', 75 | 'VUV', 76 | 'XAF', 77 | 'XOF', 78 | 'XPF', 79 | ]; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Gateway/Helper/SubjectReader.php: -------------------------------------------------------------------------------- 1 | true, 38 | 'message' => __($response['object']->getMessage()) 39 | ]; 40 | } 41 | 42 | return $response['object']->__toArray(); 43 | } 44 | 45 | /** 46 | * @codeCoverageIgnore 47 | * @param array $subject 48 | * @return \Magento\Payment\Gateway\Data\PaymentDataObjectInterface 49 | */ 50 | public function readPayment(array $subject) 51 | { 52 | return Helper\SubjectReader::readPayment($subject); 53 | } 54 | 55 | /** 56 | * @param array $subject 57 | * @return mixed 58 | */ 59 | public function readTransaction(array $subject) 60 | { 61 | if (!is_object($subject['object'])) { 62 | throw new \InvalidArgumentException('Response object does not exist'); 63 | } 64 | 65 | return $subject['object']->__toArray(); 66 | } 67 | 68 | /** 69 | * @codeCoverageIgnore 70 | * @param array $subject 71 | * @return mixed 72 | */ 73 | public function readAmount(array $subject) 74 | { 75 | return Helper\SubjectReader::readAmount($subject); 76 | } 77 | 78 | /** 79 | * @param array $subject 80 | * @return int 81 | */ 82 | public function readCustomerId(array $subject) 83 | { 84 | if (!isset($subject['customer_id'])) { 85 | throw new \InvalidArgumentException('The customerId field does not exist'); 86 | } 87 | 88 | return (int)$subject['customer_id']; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/Gateway/Http/Client/AbstractTransaction.php: -------------------------------------------------------------------------------- 1 | logger = $logger; 64 | $this->customLogger = $customLogger; 65 | $this->adapter = $adapter; 66 | $this->config = $config ?: ObjectManager::getInstance()->get(Config::class); 67 | } 68 | 69 | /** 70 | * @param TransferInterface $transferObject 71 | * @return mixed 72 | * @throws ClientException 73 | */ 74 | public function placeRequest( 75 | TransferInterface $transferObject 76 | ) 77 | { 78 | $data = $transferObject->getBody(); 79 | $log = [ 80 | 'request' => $data, 81 | 'client' => static::class 82 | ]; 83 | $response['object'] = []; 84 | 85 | try { 86 | $response['object'] = $this->process($data); 87 | } catch (\Exception $e) { 88 | $message = __($e->getMessage() ?: 'Sorry, but something went wrong.'); 89 | $this->logger->critical($e); 90 | throw new ClientException($message); 91 | } finally { 92 | if ($response['object'] instanceof \Stripe\Error\Base 93 | || $response['object'] instanceof \Stripe\StripeObject 94 | ) { 95 | $log['response'] = $response['object']->__toString(); 96 | } else { 97 | $log['response'] = $response['object']; 98 | } 99 | 100 | $this->customLogger->debug($log); 101 | } 102 | 103 | return $response; 104 | } 105 | 106 | /** 107 | * @param array $data 108 | * @return mixed 109 | */ 110 | abstract protected function process(array $data); 111 | } 112 | -------------------------------------------------------------------------------- /src/Gateway/Http/Client/TransactionRefund.php: -------------------------------------------------------------------------------- 1 | adapter->refund( 30 | $data['transaction_id'], 31 | $data[PaymentDataBuilder::AMOUNT] 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Gateway/Http/Client/TransactionSale.php: -------------------------------------------------------------------------------- 1 | adapter->sale($data); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Gateway/Http/Client/TransactionSubmitForSettlement.php: -------------------------------------------------------------------------------- 1 | adapter->submitForSettlement( 32 | $data[CaptureDataBuilder::TRANSACTION_ID], 33 | $data[PaymentDataBuilder::AMOUNT] 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Gateway/Http/Client/TransactionVoid.php: -------------------------------------------------------------------------------- 1 | adapter->void($data['transaction_id']); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Gateway/Http/TransferFactory.php: -------------------------------------------------------------------------------- 1 | transferBuilder = $transferBuilder; 38 | } 39 | 40 | /** 41 | * @param array $request 42 | * @return TransferInterface 43 | */ 44 | public function create(array $request) 45 | { 46 | return $this->transferBuilder 47 | ->setBody($request) 48 | ->build(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Gateway/Request/AddressDataBuilder.php: -------------------------------------------------------------------------------- 1 | subjectReader = $subjectReader; 47 | } 48 | 49 | /** 50 | * @param array $buildSubject 51 | * @return array 52 | */ 53 | public function build(array $buildSubject) 54 | { 55 | $paymentDataObject = $this->subjectReader->readPayment($buildSubject); 56 | 57 | $order = $paymentDataObject->getOrder(); 58 | $result = []; 59 | 60 | $shippingAddress = $order->getShippingAddress(); 61 | if ($shippingAddress) { 62 | $result[self::SHIPPING_ADDRESS] = [ 63 | 'address' => [ 64 | self::STREET_ADDRESS => $shippingAddress->getStreetLine1(), 65 | self::EXTENDED_ADDRESS => $shippingAddress->getStreetLine2(), 66 | self::LOCALITY => $shippingAddress->getCity(), 67 | self::REGION => $shippingAddress->getRegionCode(), 68 | self::POSTAL_CODE => $shippingAddress->getPostcode(), 69 | self::COUNTRY_CODE => $shippingAddress->getCountryId() 70 | ], 71 | self::NAME => $shippingAddress->getFirstname() . ' ' . $shippingAddress->getLastname(), 72 | self::PHONE => $shippingAddress->getTelephone() 73 | ]; 74 | } 75 | 76 | return $result; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Gateway/Request/CaptureDataBuilder.php: -------------------------------------------------------------------------------- 1 | subjectReader = $subjectReader; 45 | $this->priceFormatter = $priceFormatter; 46 | } 47 | 48 | /** 49 | * @param array $subject 50 | * @return array 51 | * @throws LocalizedException 52 | */ 53 | public function build(array $subject) 54 | { 55 | $paymentDataObject = $this->subjectReader->readPayment($subject); 56 | $payment = $paymentDataObject->getPayment(); 57 | $transactionId = $payment->getCcTransId(); 58 | 59 | if (!$transactionId) { 60 | throw new LocalizedException(__('No Authorization Transaction to capture')); 61 | } 62 | 63 | return [ 64 | self::TRANSACTION_ID => $transactionId, 65 | PaymentDataBuilder::AMOUNT => $this->priceFormatter->formatPrice($this->subjectReader->readAmount($subject)) 66 | ]; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Gateway/Request/PaymentDataBuilder/Admin.php: -------------------------------------------------------------------------------- 1 | adminSession = $session; 57 | } 58 | 59 | /** 60 | * @return string 61 | */ 62 | protected function getStripeCustomerId() 63 | { 64 | $customer = $this->customerRepository->getById($this->adminSession->getCustomerId()); 65 | $stripeCustomerId = $customer->getCustomAttribute('stripe_customer_id'); 66 | 67 | if (!$stripeCustomerId) { 68 | $stripeCustomerId = $this->createNewStripeCustomer($customer->getEmail()); 69 | $customer->setCustomAttribute( 70 | 'stripe_customer_id', 71 | $stripeCustomerId 72 | ); 73 | 74 | $this->customerRepository->save($customer); 75 | 76 | return $stripeCustomerId; 77 | } 78 | 79 | return $stripeCustomerId->getValue(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Gateway/Request/PaymentDataBuilder/Vault.php: -------------------------------------------------------------------------------- 1 | subjectReader->readPayment($subject); 30 | $payment = $paymentDataObject->getPayment(); 31 | $order = $paymentDataObject->getOrder(); 32 | 33 | $extensionAttributes = $payment->getExtensionAttributes(); 34 | $paymentToken = $extensionAttributes->getVaultPaymentToken(); 35 | 36 | $stripeCustomerId = $this->getStripeCustomerId(); 37 | 38 | $result = [ 39 | self::AMOUNT => $this->priceFormatter->formatPrice($this->subjectReader->readAmount($subject)), 40 | self::ORDER_ID => $order->getOrderIncrementId(), 41 | self::CURRENCY => $this->config->getCurrency(), 42 | self::SOURCE => $paymentToken->getGatewayToken(), 43 | self::CAPTURE => 'false', 44 | self::CUSTOMER => $stripeCustomerId 45 | ]; 46 | 47 | return $result; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Gateway/Request/PaymentDataBuilder/Vault/Admin.php: -------------------------------------------------------------------------------- 1 | adminSession = $session; 57 | } 58 | 59 | /** 60 | * @return \Magento\Framework\Api\AttributeInterface|mixed|null 61 | */ 62 | protected function getStripeCustomerId() 63 | { 64 | $customer = $this->customerRepository->getById($this->adminSession->getCustomerId()); 65 | $stripeCustomerId = $customer->getCustomAttribute('stripe_customer_id'); 66 | 67 | if (!$stripeCustomerId) { 68 | $stripeCustomerId = $this->createNewStripeCustomer($customer->getEmail()); 69 | $customer->setCustomAttribute( 70 | 'stripe_customer_id', 71 | $stripeCustomerId 72 | ); 73 | 74 | $this->customerRepository->save($customer); 75 | 76 | return $stripeCustomerId; 77 | } 78 | 79 | return $stripeCustomerId->getValue(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Gateway/Request/RefundDataBuilder.php: -------------------------------------------------------------------------------- 1 | subjectReader = $subjectReader; 46 | $this->priceFormatter = $priceFormatter; 47 | } 48 | 49 | /** 50 | * @param array $subject 51 | * @return array 52 | */ 53 | public function build(array $subject) 54 | { 55 | $paymentDataObject = $this->subjectReader->readPayment($subject); 56 | $payment = $paymentDataObject->getPayment(); 57 | $amount = null; 58 | 59 | try { 60 | $amount = $this->priceFormatter->formatPrice($this->subjectReader->readAmount($subject)); 61 | } catch (\InvalidArgumentException $e) { 62 | //nothing 63 | } 64 | 65 | $txnId = str_replace( 66 | '-' . TransactionInterface::TYPE_CAPTURE, 67 | '', 68 | $payment->getParentTransactionId() 69 | ); 70 | 71 | return [ 72 | 'transaction_id' => $txnId, 73 | PaymentDataBuilder::AMOUNT => $amount 74 | ]; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Gateway/Request/SettlementDataBuilder.php: -------------------------------------------------------------------------------- 1 | true]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Gateway/Request/ThreeDSecureBuilder.php: -------------------------------------------------------------------------------- 1 | config = $config; 47 | $this->subjectReader = $subjectReader; 48 | } 49 | 50 | /** 51 | * @param array $subject 52 | * @return array 53 | * @throws \Magento\Framework\Validator\Exception 54 | */ 55 | public function build(array $subject) 56 | { 57 | $result = []; 58 | if (!$this->config->isRequireThreeDSecure() 59 | || (float)$this->subjectReader->readAmount($subject) < $this->config->getThreeDSecureThreshold() 60 | ) { 61 | return $result; 62 | } 63 | 64 | Stripe::setApiKey($this->config->getSecretKey()); 65 | 66 | $paymentDataObject = $this->subjectReader->readPayment($subject); 67 | $payment = $paymentDataObject->getPayment(); 68 | 69 | $source = $this->getSourceForCharge($payment); 70 | if ($source) { 71 | $result[self::SOURCE] = $source; 72 | $result[self::SOURCE_FOR_VAULT] = $payment->getAdditionalInformation('cc_src'); 73 | } 74 | 75 | return $result; 76 | } 77 | 78 | /** 79 | * @param InfoInterface $payment 80 | * @return string|false 81 | */ 82 | private function getSourceForCharge($payment) 83 | { 84 | /** @var Source $threeDSource */ 85 | $threeDSource = Source::retrieve($payment->getAdditionalInformation('three_d_src')); 86 | if ($threeDSource->status === 'failed') { 87 | return $payment->getAdditionalInformation('cc_src') ?: false; 88 | } 89 | 90 | return $payment->getAdditionalInformation('three_d_src'); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/Gateway/Request/VoidDataBuilder.php: -------------------------------------------------------------------------------- 1 | subjectReader = $subjectReader; 38 | } 39 | 40 | /** 41 | * @param array $subject 42 | * @return array 43 | */ 44 | public function build(array $subject) 45 | { 46 | $paymentDataObject = $this->subjectReader->readPayment($subject); 47 | $payment = $paymentDataObject->getPayment(); 48 | 49 | return [ 50 | 'transaction_id' => $payment->getParentTransactionId() ?: $payment->getLastTransId() 51 | ]; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Gateway/Response/CardDetailsHandler.php: -------------------------------------------------------------------------------- 1 | config = $config; 51 | $this->subjectReader = $subjectReader; 52 | } 53 | 54 | /** 55 | * @param array $subject 56 | * @param array $response 57 | */ 58 | public function handle(array $subject, array $response) 59 | { 60 | $paymentDataObject = $this->subjectReader->readPayment($subject); 61 | $transaction = $this->subjectReader->readTransaction($response); 62 | $payment = $paymentDataObject->getPayment(); 63 | ContextHelper::assertOrderPayment($payment); 64 | 65 | $creditCard = $transaction['source']->__toArray(); 66 | $payment->setCcLast4($creditCard[self::CARD_LAST4]); 67 | $payment->setCcExpMonth($creditCard[self::CARD_EXP_MONTH]); 68 | $payment->setCcExpYear($creditCard[self::CARD_EXP_YEAR]); 69 | $payment->setCcType($creditCard[self::CARD_TYPE]); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Gateway/Response/PaymentDetailsHandler.php: -------------------------------------------------------------------------------- 1 | subjectReader = $subjectReader; 55 | } 56 | 57 | /** 58 | * @param array $subject 59 | * @param array $response 60 | */ 61 | public function handle(array $subject, array $response) 62 | { 63 | $paymentDataObject = $this->subjectReader->readPayment($subject); 64 | $transaction = $this->subjectReader->readTransaction($response); 65 | $payment = $paymentDataObject->getPayment(); 66 | 67 | $payment->setCcTransId($transaction['id']); 68 | $payment->setLastTransId($transaction['id']); 69 | 70 | $outcome = $transaction['outcome']->__toArray(); 71 | foreach ($this->additionalInformationMapping as $item) { 72 | if (!isset($outcome[$item])) { 73 | continue; 74 | } 75 | $payment->setAdditionalInformation($item, $outcome[$item]); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Gateway/Response/RefundHandler.php: -------------------------------------------------------------------------------- 1 | getCreditmemo()->getInvoice()->canRefund(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Gateway/Response/TransactionIdHandler.php: -------------------------------------------------------------------------------- 1 | subjectReader = $subjectReader; 38 | } 39 | 40 | /** 41 | * @param array $subject 42 | * @param array $response 43 | */ 44 | public function handle(array $subject, array $response) 45 | { 46 | $paymentDataObject = $this->subjectReader->readPayment($subject); 47 | 48 | if ($paymentDataObject->getPayment() instanceof Payment) { 49 | $transaction = $this->subjectReader->readTransaction($response); 50 | $orderPayment = $paymentDataObject->getPayment(); 51 | 52 | $this->setTransactionId( 53 | $orderPayment, 54 | $transaction 55 | ); 56 | 57 | $orderPayment->setIsTransactionClosed($this->shouldCloseTransaction()); 58 | $closed = $this->shouldCloseParentTransaction($orderPayment); 59 | $orderPayment->setShouldCloseParentTransaction($closed); 60 | } 61 | } 62 | 63 | /** 64 | * @param Payment $orderPayment 65 | * @param $transaction 66 | */ 67 | protected function setTransactionId(Payment $orderPayment, $transaction) 68 | { 69 | $orderPayment->setTransactionId($transaction['id']); 70 | } 71 | 72 | /** 73 | * @return bool 74 | */ 75 | protected function shouldCloseTransaction() 76 | { 77 | return false; 78 | } 79 | 80 | /** 81 | * @param Payment $orderPayment 82 | * @return bool 83 | */ 84 | protected function shouldCloseParentTransaction(Payment $orderPayment) 85 | { 86 | return false; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/Gateway/Response/VoidHandler.php: -------------------------------------------------------------------------------- 1 | subjectReader = $subjectReader; 41 | } 42 | 43 | /** 44 | * @param array $subject 45 | * @return \Magento\Payment\Gateway\Validator\ResultInterface 46 | */ 47 | public function validate(array $subject) 48 | { 49 | $response = $this->subjectReader->readResponseObject($subject); 50 | 51 | $isValid = true; 52 | $errorMessages = []; 53 | 54 | foreach ($this->getResponseValidators() as $validator) { 55 | $validationResult = $validator($response); 56 | 57 | if (!$validationResult[0]) { 58 | $isValid = $validationResult[0]; 59 | $errorMessages = array_merge( 60 | $errorMessages, 61 | $validationResult[1] 62 | ); 63 | break; 64 | } 65 | } 66 | 67 | return $this->createResult($isValid, $errorMessages); 68 | } 69 | 70 | /** 71 | * @return array 72 | */ 73 | protected function getResponseValidators() 74 | { 75 | return [ 76 | function ($response) { 77 | if (isset($response['error'])) { 78 | return [ 79 | false, 80 | [$response['message']] 81 | ]; 82 | } 83 | return [ 84 | $response['status'] === 'succeeded', 85 | [__('Stripe error response.')] 86 | ]; 87 | } 88 | ]; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/Gateway/Validator/ResponseValidator.php: -------------------------------------------------------------------------------- 1 | __toArray()['network_status'] === 'approved_by_network', 34 | [__('Transaction has been declined')] 35 | ]; 36 | } 37 | ] 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Helper/CcType.php: -------------------------------------------------------------------------------- 1 | ccTypeSource = $ccTypeSource; 41 | } 42 | 43 | /** 44 | * @return array 45 | */ 46 | public function getCcTypes() 47 | { 48 | if (!$this->ccTypes) { 49 | $this->ccTypes = $this->ccTypeSource->toOptionArray(); 50 | } 51 | return $this->ccTypes; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Model/Adapter/StripeSearchAdapter.php: -------------------------------------------------------------------------------- 1 | AbstractMethod::ACTION_AUTHORIZE, 32 | 'label' => __('Authorize Only'), 33 | ], 34 | [ 35 | 'value' => AbstractMethod::ACTION_AUTHORIZE_CAPTURE, 36 | 'label' => __('Authorize and Capture'), 37 | ] 38 | ]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Model/InstantPurchase/CreditCard/TokenFormatter.php: -------------------------------------------------------------------------------- 1 | 'American Express', 30 | 'VI' => 'Visa', 31 | 'MC' => 'MasterCard', 32 | 'DI' => 'Discover', 33 | 'JBC' => 'JBC', 34 | 'CUP' => 'China Union Pay', 35 | 'MI' => 'Maestro', 36 | ]; 37 | 38 | /** 39 | * @inheritdoc 40 | */ 41 | public function formatPaymentToken(PaymentTokenInterface $paymentToken): string 42 | { 43 | $details = json_decode($paymentToken->getTokenDetails() ?: '{}', true); 44 | if (!isset($details['type'], $details['maskedCC'], $details['expirationDate'])) { 45 | throw new \InvalidArgumentException('Invalid credit card token details.'); 46 | } 47 | 48 | if (isset(self::$baseCardTypes[$details['type']])) { 49 | $ccType = self::$baseCardTypes[$details['type']]; 50 | } else { 51 | $ccType = $details['type']; 52 | } 53 | 54 | $formatted = sprintf( 55 | '%s: %s, %s: %s (%s: %s)', 56 | __('Credit Card'), 57 | $ccType, 58 | __('ending'), 59 | $details['maskedCC'], 60 | __('expires'), 61 | $details['expirationDate'] 62 | ); 63 | 64 | return $formatted; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Model/Ui/Adminhtml/TokenUiComponentProvider.php: -------------------------------------------------------------------------------- 1 | componentFactory = $componentFactory; 59 | $this->urlBuilder = $urlBuilder; 60 | $this->jsonDecoder = $decoder; 61 | } 62 | 63 | /** 64 | * Get UI component for token 65 | * @param PaymentTokenInterface $paymentToken 66 | * @return TokenUiComponentInterface 67 | */ 68 | public function getComponentForToken(PaymentTokenInterface $paymentToken) 69 | { 70 | $jsonDetails = $this->jsonDecoder->decode($paymentToken->getTokenDetails() ?: '{}'); 71 | 72 | $component = $this->componentFactory->create( 73 | [ 74 | 'config' => [ 75 | 'code' => ConfigProvider::CC_VAULT_CODE, 76 | TokenUiComponentProviderInterface::COMPONENT_DETAILS => $jsonDetails, 77 | TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH => $paymentToken->getPublicHash(), 78 | 'template' => 'Pmclain_Stripe::form/vault.phtml', 79 | ], 80 | 'name' => Template::class, 81 | ] 82 | ); 83 | 84 | return $component; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Model/Ui/ConfigProvider.php: -------------------------------------------------------------------------------- 1 | config = $configInterface; 50 | $this->url = $url; 51 | } 52 | 53 | /** 54 | * @return array 55 | */ 56 | public function getConfig() 57 | { 58 | return [ 59 | 'payment' => [ 60 | self::CODE => [ 61 | 'publishableKey' => $this->getPublishableKey(), 62 | 'threeDSecure' => (int)$this->getStoreConfig(Config::KEY_VERIFY_3D_SECURE), 63 | 'threeDThreshold' => (float)$this->getStoreConfig(Config::KEY_3D_SECURE_THRESHOLD), 64 | 'threeDRedirectUrl' => $this->url->getUrl('pmstripe/threedsecure/redirect'), 65 | 'vaultCode' => self::CC_VAULT_CODE, 66 | ], 67 | ], 68 | ]; 69 | } 70 | 71 | /** 72 | * @return string 73 | */ 74 | public function getPublishableKey() 75 | { 76 | if ($this->isTestMode()) { 77 | return $this->getStoreConfig(Config::KEY_TEST_PUBLISHABLE_KEY); 78 | } 79 | return $this->getStoreConfig(Config::KEY_LIVE_PUBLISHABLE_KEY); 80 | } 81 | 82 | /** 83 | * @return int 84 | */ 85 | protected function isTestMode() 86 | { 87 | return (int)$this->getStoreConfig(Config::KEY_ENVIRONMENT); 88 | } 89 | 90 | /** 91 | * @param string $value 92 | * @return mixed 93 | */ 94 | protected function getStoreConfig($value) 95 | { 96 | return $this->config->getValue( 97 | 'payment/pmclain_stripe/' . $value, 98 | ScopeInterface::SCOPE_STORE 99 | ); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Model/Ui/TokenUiComponentProvider.php: -------------------------------------------------------------------------------- 1 | componentFactory = $componentFactory; 65 | $this->urlBuilder = $urlBuilder; 66 | $this->jsonDecoder = $decoder; 67 | $this->config = $config; 68 | } 69 | 70 | /** 71 | * Get UI component for token 72 | * @param PaymentTokenInterface $paymentToken 73 | * @return TokenUiComponentInterface 74 | */ 75 | public function getComponentForToken(PaymentTokenInterface $paymentToken) 76 | { 77 | $jsonDetails = $this->jsonDecoder->decode($paymentToken->getTokenDetails() ?: '{}'); 78 | $jsonDetails['source'] = $this->getSource($paymentToken); 79 | 80 | $component = $this->componentFactory->create( 81 | [ 82 | 'config' => [ 83 | 'code' => ConfigProvider::CC_VAULT_CODE, 84 | TokenUiComponentProviderInterface::COMPONENT_DETAILS => $jsonDetails, 85 | TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH => $paymentToken->getPublicHash(), 86 | ], 87 | 'name' => 'Pmclain_Stripe/js/view/payment/method-renderer/vault', 88 | ] 89 | ); 90 | 91 | return $component; 92 | } 93 | 94 | /** 95 | * @param PaymentTokenInterface $paymentToken 96 | * @return string 97 | */ 98 | private function getSource($paymentToken) 99 | { 100 | if ($this->config->isRequireThreeDSecure()) { 101 | return $paymentToken->getGatewayToken(); 102 | } 103 | 104 | return ''; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/Observer/DataAssignObserver.php: -------------------------------------------------------------------------------- 1 | readDataArgument($observer); 36 | 37 | $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); 38 | if (!is_array($additionalData)) { 39 | return; 40 | } 41 | 42 | $additionalData = new DataObject($additionalData); 43 | 44 | $payment = $observer->getPaymentModel(); 45 | if (!$payment instanceof InfoInterface) { 46 | $payment = $this->readMethodArgument($observer)->getInfoInstance(); 47 | } 48 | 49 | if (!$payment instanceof InfoInterface) { 50 | throw new LocalizedException(__('Payment model does not provided.')); 51 | } 52 | 53 | $payment->setCcLast4($additionalData->getData('cc_last4')); 54 | $payment->setCcType($additionalData->getData('cc_type')); 55 | $payment->setCcExpMonth($additionalData->getData('cc_exp_month')); 56 | $payment->setCcExpYear($additionalData->getData('cc_exp_year')); 57 | 58 | if ($additionalData->getData('cc_token')) { 59 | $payment->setAdditionalInformation('cc_token', $additionalData->getData('cc_token')); 60 | } 61 | if ($additionalData->getData('cc_src')) { 62 | $payment->setAdditionalInformation('cc_src', $additionalData->getData('cc_src')); 63 | } 64 | if ($additionalData->getData('three_d_src')) { 65 | $payment->setAdditionalInformation('three_d_src', $additionalData->getData('three_d_src')); 66 | } 67 | if ($additionalData->getData('three_d_client_secret')) { 68 | $payment->setAdditionalInformation('three_d_client_secret', $additionalData->getData('three_d_client_secret')); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Observer/VaultTokenObserver.php: -------------------------------------------------------------------------------- 1 | config = $config; 44 | $this->customerRepository = $customerRepository; 45 | $this->initCredentials(); 46 | } 47 | 48 | protected function initCredentials() 49 | { 50 | Stripe::setApiKey($this->config->getSecretKey()); 51 | } 52 | 53 | /** 54 | * @param Observer $observer 55 | */ 56 | public function execute(Observer $observer) 57 | { 58 | $token = $observer->getObject(); 59 | if ($token->getIsActive()) { 60 | return; 61 | } 62 | 63 | try { 64 | $customer = $this->customerRepository->getById($token->getCustomerId()); 65 | } catch (\Exception $e) { 66 | return; 67 | } 68 | 69 | $stripeCustomerId = $customer->getCustomAttribute('stripe_customer_id'); 70 | if (!$stripeCustomerId) { 71 | return; 72 | } 73 | 74 | try { 75 | $stripeCustomer = Customer::retrieve($stripeCustomerId->getValue()); 76 | $stripeCustomer->sources->retrieve($token->getGatewayToken())->delete(); 77 | } catch (\Exception $e) { 78 | return; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Setup/InstallData.php: -------------------------------------------------------------------------------- 1 | eavSetupFactory = $eavSetupFactory; 33 | $this->eavConfig = $config; 34 | } 35 | 36 | public function install( 37 | ModuleDataSetupInterface $setup, 38 | ModuleContextInterface $context 39 | ) { 40 | $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); 41 | $eavSetup->addAttribute( 42 | Customer::ENTITY, 43 | 'stripe_customer_id', 44 | [ 45 | 'type' => 'varchar', 46 | 'label' => 'Stripe Customer ID', 47 | 'input' => 'text', 48 | 'required' => false, 49 | 'sort_order' => 100, 50 | 'system' => false, 51 | 'position' => 100, 52 | ] 53 | ); 54 | 55 | $stripeCustomerIdAttribute = $this->eavConfig->getAttribute( 56 | Customer::ENTITY, 57 | 'stripe_customer_id' 58 | ); 59 | $stripeCustomerIdAttribute->setData( 60 | 'used_in_forms', 61 | [ 62 | 'adminhtml_customer', 63 | ] 64 | ); 65 | $stripeCustomerIdAttribute->save(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Setup/UpgradeData.php: -------------------------------------------------------------------------------- 1 | eavSetupFactory = $eavSetupFactory; 33 | $this->eavConfig = $config; 34 | } 35 | 36 | /** 37 | * @param ModuleDataSetupInterface $setup 38 | * @param ModuleContextInterface $context 39 | */ 40 | public function upgrade( 41 | ModuleDataSetupInterface $setup, 42 | ModuleContextInterface $context 43 | ) { 44 | if (version_compare($context->getVersion(), '0.0.2') < 0) { 45 | $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); 46 | $eavSetup->addAttribute( 47 | Customer::ENTITY, 48 | 'stripe_customer_id', 49 | [ 50 | 'type' => 'varchar', 51 | 'label' => 'Strip Customer ID', 52 | 'input' => 'text', 53 | 'required' => false, 54 | 'sort_order' => 100, 55 | 'system' => false, 56 | 'position' => 100, 57 | ] 58 | ); 59 | 60 | $stripeCustomerIdAttribute = $this->eavConfig->getAttribute( 61 | Customer::ENTITY, 62 | 'stripe_customer_id' 63 | ); 64 | $stripeCustomerIdAttribute->setData( 65 | 'used_in_forms', 66 | [ 67 | 'adminhtml_customer', 68 | ] 69 | ); 70 | $stripeCustomerIdAttribute->save(); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Test/Acceptance/ActionGroup/CompleteGuestAddressFormActionGroup.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/Test/Acceptance/ActionGroup/CompleteStripePaymentFormActionGroup.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/Test/Acceptance/ActionGroup/GetToCheckoutActionGroup.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/Test/Acceptance/ActionGroup/ValidateOrderActionGroup.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/Test/Acceptance/Data/CardData.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 4111111111111111 22 | 03/25 23 | 123 24 | 25 | 26 | 4000000000003055 27 | 03/25 28 | 123 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/Test/Acceptance/Data/StripeConfigData.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | SampleActive 22 | SampleTestMode 23 | SampleSecretKey 24 | SamplePublishableKey 25 | SampleVerify3dSecure 26 | 27 | 28 | 1 29 | 30 | 31 | 1 32 | 33 | 34 | sk_test_aODtklwVgFxCRNfctGuc2zr9 35 | 36 | 37 | pk_test_QWPtpvIqEoG51jNCWqO9HZOC 38 | 39 | 40 | 1 41 | 42 | 43 | 44 | 45 | DefaultActive 46 | DefaultTestMode 47 | SampleSecretKey 48 | SamplePublishableKey 49 | DefaultVerify3dSecure 50 | 51 | 52 | 0 53 | 54 | 55 | 0 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 0 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/Test/Acceptance/Metadata/stripe_config-meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | integer 26 | 27 | 28 | integer 29 | 30 | 31 | string 32 | 33 | 34 | string 35 | 36 | 37 | integer 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/Test/Acceptance/Section/CheckoutPaymentSection.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 |
29 | -------------------------------------------------------------------------------- /src/Test/Acceptance/Section/StripeIframeSection.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 |
21 | 22 | 23 | 24 |
25 |
26 | -------------------------------------------------------------------------------- /src/Test/Acceptance/Section/ThreeDConfirmationSection.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 |
21 | 22 |
23 |
24 | -------------------------------------------------------------------------------- /src/Test/Acceptance/Test/StorefrontStripeCustomerCheckoutTest.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | <description value="Checkout as customer using Stripe"/> 26 | <severity value="CRITICAL"/> 27 | <group value="pmclain_stripe"/> 28 | </annotations> 29 | <before> 30 | <createData entity="SampleStripeConfig" stepKey="createSampleStripeConfig" /> 31 | <createData entity="_defaultCategory" stepKey="createCategory"/> 32 | <createData entity="_defaultProduct" stepKey="createProduct"> 33 | <requiredEntity createDataKey="createCategory"/> 34 | </createData> 35 | <createData entity="Simple_US_Customer" stepKey="simpleuscustomer"/> 36 | </before> 37 | <after> 38 | <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> 39 | <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> 40 | <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> 41 | <createData entity="DefaultStripeConfig" stepKey="restoreDefaultStripeConfig" /> 42 | <deleteData createDataKey="simpleuscustomer" stepKey="deleteCustomer" /> 43 | </after> 44 | 45 | <actionGroup ref="CustomerLoginOnStorefront" stepKey="customerLogin"> 46 | <argument name="customer" value="$$simpleuscustomer$$" /> 47 | </actionGroup> 48 | 49 | <actionGroup ref="GetToCheckout" stepKey="proceedToCheckout"> 50 | <argument name="category" value="$$createCategory$$" /> 51 | </actionGroup> 52 | 53 | <waitForElement selector="{{CheckoutShippingMethodsSection.next}}" time="30" stepKey="waitForNextButton"/> 54 | <click selector="{{CheckoutShippingMethodsSection.next}}" stepKey="clickNext"/> 55 | 56 | <actionGroup ref="CompleteStripePaymentForm" stepKey="enterPaymentDetails"> 57 | <argument name="card" value="stripeCardValid" /> 58 | </actionGroup> 59 | 60 | <click selector="{{CheckoutPaymentSection.saveInVault}}" stepKey="uncheckSaveInVault" /> 61 | <click selector="{{CheckoutPaymentSection.stripePlaceOrder}}" stepKey="clickPlaceOrderButton" /> 62 | <waitForPageLoad stepKey="waitForSuccessPage" time="60" /> 63 | 64 | <grabTextFrom stepKey="grabOrderNumber" selector="{{CheckoutSuccessMainSection.orderNumber22}}"/> 65 | <see stepKey="seeOrderConfirmation" selector="{{CheckoutSuccessMainSection.success}}" userInput="Your order number is:" /> 66 | 67 | <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> 68 | 69 | <actionGroup ref="ValidateOrder" stepKey="adminCheckOrder"> 70 | <argument name="ordernumber" value="$grabOrderNumber" /> 71 | <argument name="email" value="$$simpleuscustomer.email$$" /> 72 | <argument name="product" value="_defaultProduct" /> 73 | </actionGroup> 74 | </test> 75 | </tests> 76 | -------------------------------------------------------------------------------- /src/Test/Acceptance/Test/StorefrontStripeGuestCheckoutTest.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | /** 4 | * Pmclain_Stripe extension 5 | * NOTICE OF LICENSE 6 | * 7 | * This source file is subject to the OSL 3.0 License 8 | * that is bundled with this package in the file LICENSE.txt. 9 | * It is also available through the world-wide-web at this URL: 10 | * https://opensource.org/licenses/osl-3.0.php 11 | * 12 | * @category Pmclain 13 | * @package Pmclain_Stripe 14 | * @copyright Copyright (c) 2017-2018 15 | * @license Open Software License (OSL 3.0) 16 | */ 17 | --> 18 | <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 19 | xsi:noNamespaceSchemaLocation="../../../../dev/magento/dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> 20 | <test name="StorefrontStripeGuestCheckout"> 21 | <annotations> 22 | <features value="Checkout"/> 23 | <stories value="Checkout via Guest Checkout"/> 24 | <title value="Guest Checkout"/> 25 | <description value="Should be able to place an order as a Guest with Stripe."/> 26 | <severity value="CRITICAL"/> 27 | <group value="pmclain_stripe"/> 28 | </annotations> 29 | <before> 30 | <createData entity="SampleStripeConfig" stepKey="createSampleStripeConfig" /> 31 | <createData entity="_defaultCategory" stepKey="createCategory"/> 32 | <createData entity="_defaultProduct" stepKey="createProduct"> 33 | <requiredEntity createDataKey="createCategory"/> 34 | </createData> 35 | </before> 36 | <after> 37 | <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> 38 | <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> 39 | <deleteData createDataKey="createProduct" stepKey="deleteProduct"/> 40 | <createData entity="DefaultStripeConfig" stepKey="restoreDefaultStripeConfig" /> 41 | </after> 42 | 43 | <actionGroup ref="GetToCheckout" stepKey="proceedToCheckout"> 44 | <argument name="category" value="$$createCategory$$" /> 45 | </actionGroup> 46 | 47 | <actionGroup ref="CompleteGuestAddressForm" stepKey="completeGuestAddressForm"> 48 | <argument name="customer" value="CustomerEntityOne" /> 49 | <argument name="address" value="CustomerAddressSimple" /> 50 | </actionGroup> 51 | 52 | <waitForLoadingMaskToDisappear stepKey="waitForLoadingMask"/> 53 | <click selector="{{GuestCheckoutShippingSection.firstShippingMethod}}" stepKey="selectFirstShippingMethod"/> 54 | <waitForElement selector="{{GuestCheckoutShippingSection.next}}" time="30" stepKey="waitForNextButton"/> 55 | <click selector="{{GuestCheckoutShippingSection.next}}" stepKey="clickNext"/> 56 | 57 | <actionGroup ref="CompleteStripePaymentForm" stepKey="enterPaymentDetails"> 58 | <argument name="card" value="stripeCardValid" /> 59 | </actionGroup> 60 | 61 | <click selector="{{CheckoutPaymentSection.stripePlaceOrder}}" stepKey="clickPlaceOrderButton" /> 62 | <waitForPageLoad stepKey="waitForSuccessPage" time="60" /> 63 | 64 | <grabTextFrom selector="{{CheckoutSuccessMainSection.orderNumber}}" stepKey="grabOrderNumber"/> 65 | <see selector="{{CheckoutSuccessMainSection.success}}" userInput="Your order # is:" stepKey="seeOrderNumber"/> 66 | <see selector="{{CheckoutSuccessMainSection.success}}" userInput="We'll email you an order confirmation with details and tracking info." stepKey="seeEmailYou"/> 67 | 68 | <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin1"/> 69 | 70 | <actionGroup ref="ValidateOrder" stepKey="adminCheckOrder"> 71 | <argument name="ordernumber" value="$grabOrderNumber" /> 72 | <argument name="email" value="{{CustomerEntityOne.email}}" /> 73 | <argument name="product" value="_defaultProduct" /> 74 | </actionGroup> 75 | </test> 76 | </tests> 77 | -------------------------------------------------------------------------------- /src/Test/Acceptance/etc/.env.dist: -------------------------------------------------------------------------------- 1 | MAGENTO_BASE_URL=http://stripe.docker/ 2 | 3 | MAGENTO_BACKEND_NAME=admin 4 | MAGENTO_ADMIN_USERNAME=admin 5 | MAGENTO_ADMIN_PASSWORD=passwd123 6 | 7 | SELENIUM_HOST=chrome 8 | SELENIUM_PORT=4444 9 | SELENIUM_PROTOCOL=http 10 | SELENIUM_PATH=/wd/hub 11 | 12 | CUSTOM_MODULE_PATHS=/module/src/Test/Acceptance 13 | 14 | #MFTF_DEBUG=true 15 | -------------------------------------------------------------------------------- /src/Test/Integration/Model/StripeAdapterTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | namespace Pmclain\Stripe\Unit\Integration\Model; 17 | 18 | use PHPUnit\Framework\TestCase; 19 | use PHPUnit_Framework_MockObject_MockObject as MockObject; 20 | use Magento\TestFramework\Helper\Bootstrap; 21 | use Magento\Framework\ObjectManagerInterface; 22 | use Pmclain\Stripe\Gateway\Request\PaymentDataBuilder; 23 | use Stripe\Stripe; 24 | use Pmclain\Stripe\Model\Adapter\StripeAdapter; 25 | use Pmclain\Stripe\Gateway\Config\Config; 26 | 27 | class StripeAdapterTest extends TestCase 28 | { 29 | const STRIPE_MOCK_URL = 'http://stripemock:12111'; 30 | const STRIPE_MOCK_API_KEY = 'sk_test_123'; 31 | 32 | /** 33 | * @var ObjectManagerInterface 34 | */ 35 | private $objectManager; 36 | 37 | /** 38 | * @var StripeAdapter 39 | */ 40 | private $adapter; 41 | 42 | /** 43 | * @var Config|MockObject 44 | */ 45 | private $configMock; 46 | 47 | protected function setUp() 48 | { 49 | $this->objectManager = Bootstrap::getObjectManager(); 50 | Stripe::$apiBase = self::STRIPE_MOCK_URL; 51 | 52 | $this->configMock = $this->createMock(Config::class); 53 | $this->configMock->method('getSecretKey') 54 | ->willReturn(self::STRIPE_MOCK_API_KEY); 55 | 56 | $this->adapter = $this->objectManager->create( 57 | StripeAdapter::class, 58 | [ 59 | 'config' => $this->configMock, 60 | ] 61 | ); 62 | } 63 | 64 | public function testRefund() 65 | { 66 | $result = $this->adapter->refund('ch_1Bh7'); 67 | 68 | $this->assertInstanceOf(\Stripe\Refund::class, $result); 69 | } 70 | 71 | public function testSale() 72 | { 73 | $attributes = [ 74 | PaymentDataBuilder::CAPTURE => false, 75 | PaymentDataBuilder::AMOUNT => '1000', 76 | PaymentDataBuilder::CURRENCY => 'USD', 77 | PaymentDataBuilder::ORDER_ID => '100000001', 78 | PaymentDataBuilder::SOURCE => 'tok_visa', 79 | ]; 80 | 81 | $result = $this->adapter->sale($attributes); 82 | 83 | $this->assertInstanceOf(\Stripe\Charge::class, $result); 84 | } 85 | 86 | public function testSaleSaveInVault() 87 | { 88 | $attributes = [ 89 | PaymentDataBuilder::SAVE_IN_VAULT => true, 90 | PaymentDataBuilder::CAPTURE => false, 91 | PaymentDataBuilder::CUSTOMER => 'cus_C5IP3', 92 | PaymentDataBuilder::AMOUNT => '1000', 93 | PaymentDataBuilder::CURRENCY => 'USD', 94 | PaymentDataBuilder::ORDER_ID => '100000001', 95 | PaymentDataBuilder::SOURCE => 'tok_visa', 96 | ]; 97 | 98 | $result = $this->adapter->sale($attributes); 99 | 100 | $this->assertInstanceOf(\Stripe\Charge::class, $result); 101 | } 102 | 103 | public function testSubmitForSettlement() 104 | { 105 | $result = $this->adapter->submitForSettlement('ch_1Bh7'); 106 | 107 | $this->assertInstanceOf(\Stripe\Charge::class, $result); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/Test/Integration/etc/install-config-mysql.php.dist: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Copyright © Magento, Inc. All rights reserved. 4 | * See COPYING.txt for license details. 5 | */ 6 | 7 | return [ 8 | 'db-host' => 'db', 9 | 'db-user' => 'magento', 10 | 'db-password' => 'magento', 11 | 'db-name' => 'magento', 12 | 'db-prefix' => '', 13 | 'backend-frontname' => 'backend', 14 | 'admin-user' => \Magento\TestFramework\Bootstrap::ADMIN_NAME, 15 | 'admin-password' => \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD, 16 | 'admin-email' => \Magento\TestFramework\Bootstrap::ADMIN_EMAIL, 17 | 'admin-firstname' => \Magento\TestFramework\Bootstrap::ADMIN_FIRSTNAME, 18 | 'admin-lastname' => \Magento\TestFramework\Bootstrap::ADMIN_LASTNAME, 19 | 'session-save' => 'redis', 20 | 'session-save-redis-host' => 'redis', 21 | 'session-save-redis-db' => '0', 22 | 'admin-use-security-key' => '0', 23 | ]; 24 | -------------------------------------------------------------------------------- /src/Test/Integration/phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | /** 4 | * Copyright © Magento, Inc. All rights reserved. 5 | * See COPYING.txt for license details. 6 | */ 7 | --> 8 | <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 9 | xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.2/phpunit.xsd" 10 | colors="true" 11 | beStrictAboutTestsThatDoNotTestAnything="false" 12 | bootstrap="./framework/bootstrap.php" 13 | stderr="true" 14 | > 15 | <!-- Test suites definition --> 16 | <testsuites> 17 | <testsuite name="Pmclain Stripe Integration Tests"> 18 | <directory suffix="Test.php">../../../vendor/pmclain/module-stripe/src/Test/Integration</directory> 19 | </testsuite> 20 | </testsuites> 21 | <!-- Code coverage filters --> 22 | <filter> 23 | <whitelist addUncoveredFilesFromWhiteList="true"> 24 | <directory suffix=".php">../../../vendor/pmclain/module-stripe/src</directory> 25 | <exclude> 26 | <directory>../../../vendor/pmclain/module-stripe/src/Test</directory> 27 | </exclude> 28 | </whitelist> 29 | </filter> 30 | <!-- PHP INI settings and constants definition --> 31 | <php> 32 | <includePath>.</includePath> 33 | <includePath>testsuite</includePath> 34 | <ini name="date.timezone" value="America/Los_Angeles"/> 35 | <ini name="xdebug.max_nesting_level" value="200"/> 36 | <const name="TESTS_INSTALL_CONFIG_FILE" value="etc/install-config-mysql.php"/> 37 | <const name="TESTS_GLOBAL_CONFIG_FILE" value="etc/config-global.php"/> 38 | <const name="TESTS_GLOBAL_CONFIG_DIR" value="../../../app/etc"/> 39 | <const name="TESTS_CLEANUP" value="disabled" /> 40 | <const name="TESTS_MEM_LEAK_LIMIT" value=""/> 41 | <const name="TESTS_EXTRA_VERBOSE_LOG" value="1"/> 42 | <const name="TESTS_MAGENTO_MODE" value="production"/> 43 | <const name="TESTS_ERROR_LOG_LISTENER_LEVEL" value="-1"/> 44 | </php> 45 | <!-- Test listeners --> 46 | <listeners> 47 | <listener class="Magento\TestFramework\Event\PhpUnit"/> 48 | <listener class="Magento\TestFramework\ErrorLog\Listener"/> 49 | </listeners> 50 | <logging> 51 | <log type="coverage-clover" target="coverage/clover.xml"/> 52 | </logging> 53 | </phpunit> 54 | -------------------------------------------------------------------------------- /src/Test/Unit/Block/InfoTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | 17 | namespace Pmclain\Stripe\Test\Unit\Block; 18 | 19 | use PHPUnit_Framework_MockObject_MockObject as MockObject; 20 | use Pmclain\Stripe\Block\Info; 21 | use Magento\Framework\View\Element\Template\Context; 22 | use Magento\Payment\Gateway\ConfigInterface; 23 | use Magento\Vault\Api\PaymentTokenManagementInterface; 24 | use Magento\Framework\Serialize\Serializer\Json; 25 | use Magento\Sales\Model\Order\Payment; 26 | use Magento\Vault\Api\Data\PaymentTokenInterface; 27 | 28 | class InfoTest extends \PHPUnit\Framework\TestCase 29 | { 30 | /** 31 | * @var PaymentTokenInterface|MockObject 32 | */ 33 | private $paymentTokenMock; 34 | 35 | /** 36 | * @var Payment|MockObject 37 | */ 38 | private $paymentMock; 39 | 40 | /** 41 | * @var PaymentTokenManagementInterface|MockObject 42 | */ 43 | private $paymentTokenManagementMock; 44 | 45 | /** 46 | * @var ConfigInterface|MockObject 47 | */ 48 | private $configMock; 49 | 50 | /** 51 | * @var Context|MockObject 52 | */ 53 | private $contextMock; 54 | 55 | /** 56 | * @var Info 57 | */ 58 | private $block; 59 | 60 | protected function setUp() 61 | { 62 | $this->paymentTokenMock = $this->createMock(PaymentTokenInterface::class); 63 | $this->paymentTokenManagementMock = $this->createMock(PaymentTokenManagementInterface::class); 64 | $this->configMock = $this->createMock(ConfigInterface::class); 65 | $this->contextMock = $this->createMock(Context::class); 66 | $this->paymentMock = $this->createMock(Payment::class); 67 | 68 | $this->paymentTokenManagementMock->method('getByPublicHash')->willReturn($this->paymentTokenMock); 69 | $this->paymentTokenMock->method('getTokenDetails')->willReturn(json_encode([ 70 | 'type' => 'AE', 71 | 'maskedCC' => '4444', 72 | 'expirationDate' => '12/29' 73 | ])); 74 | 75 | $this->block = new Info( 76 | $this->contextMock, 77 | $this->configMock, 78 | $this->paymentTokenManagementMock, 79 | new Json() 80 | ); 81 | 82 | $this->block->setData('info', $this->paymentMock); 83 | } 84 | 85 | public function testGetSpecificInformationFromToken() 86 | { 87 | $expected = [ 88 | 'Card Type' => 'American Express', 89 | 'Card Last 4 Digits' => '4444', 90 | ]; 91 | 92 | $this->assertEquals($expected, $this->block->getSpecificInformation()); 93 | } 94 | 95 | public function testGetSpecificInformation() 96 | { 97 | $expected = [ 98 | 'Card Type' => 'American Express', 99 | 'Card Last 4 Digits' => '4444', 100 | ]; 101 | 102 | $this->paymentMock->method('getCcType')->willReturn('American Express'); 103 | $this->paymentMock->method('getCcLast4')->willReturn('4444'); 104 | 105 | $this->assertEquals($expected, $this->block->getSpecificInformation()); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/Test/Unit/Block/PaymentTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | 17 | namespace Pmclain\Stripe\Test\Unit\Block; 18 | 19 | use Pmclain\Stripe\Block\Payment; 20 | use \PHPUnit_Framework_MockObject_MockObject as MockObject; 21 | use Pmclain\Stripe\Model\Ui\ConfigProvider; 22 | 23 | class PaymentTest extends \PHPUnit\Framework\TestCase 24 | { 25 | /** @var ConfigProvider|MockObject */ 26 | private $configProviderMock; 27 | 28 | /** @var Payment */ 29 | private $block; 30 | 31 | protected function setUp() 32 | { 33 | $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); 34 | 35 | $this->configProviderMock = $this->getMockBuilder(ConfigProvider::class) 36 | ->disableOriginalConstructor() 37 | ->getMock(); 38 | 39 | $this->block = $objectManager->getObject( 40 | Payment::class, 41 | [ 42 | 'config' => $this->configProviderMock 43 | ] 44 | ); 45 | } 46 | 47 | public function testGetPaymentConfig() 48 | { 49 | $this->configProviderMock->expects($this->once()) 50 | ->method('getConfig'); 51 | 52 | $this->block->getPaymentConfig(); 53 | } 54 | 55 | public function testGetCode() 56 | { 57 | $this->assertEquals( 58 | ConfigProvider::CODE, 59 | $this->block->getCode() 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Test/Unit/Gateway/Config/CanVoidHandlerTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | 17 | namespace Pmclain\Stripe\Test\Unit\Gateway\Config; 18 | 19 | use Pmclain\Stripe\Gateway\Config\CanVoidHandler; 20 | use Pmclain\Stripe\Gateway\Helper\SubjectReader; 21 | use Magento\Payment\Gateway\Data\PaymentDataObjectInterface; 22 | use Magento\Payment\Model\InfoInterface; 23 | use Magento\Sales\Model\Order\Payment; 24 | 25 | class CanVoidHandlerTest extends \PHPUnit\Framework\TestCase 26 | { 27 | public function testHandleNotOrderPayment() 28 | { 29 | $paymentDataObject = $this->createMock(PaymentDataObjectInterface::class); 30 | $subject = ['payment' => $paymentDataObject]; 31 | 32 | $subjectReader = $this->getMockBuilder(SubjectReader::class) 33 | ->disableOriginalConstructor() 34 | ->getMock(); 35 | 36 | $subjectReader->expects(static::once()) 37 | ->method('readPayment') 38 | ->willReturn($paymentDataObject); 39 | 40 | $paymentMock = $this->createMock(InfoInterface::class); 41 | 42 | $paymentDataObject->expects(static::once()) 43 | ->method('getPayment') 44 | ->willReturn($paymentMock); 45 | 46 | $voidHandler = new CanVoidHandler($subjectReader); 47 | 48 | $this->assertFalse($voidHandler->handle($subject)); 49 | } 50 | 51 | public function testHandleSomeAmountWasPaid() 52 | { 53 | $paymentDataObject = $this->createMock(PaymentDataObjectInterface::class); 54 | $subject = ['payment' => $paymentDataObject]; 55 | 56 | $subjectReader = $this->getMockBuilder(SubjectReader::class) 57 | ->disableOriginalConstructor() 58 | ->getMock(); 59 | 60 | $subjectReader->expects(static::once()) 61 | ->method('readPayment') 62 | ->willReturn($paymentDataObject); 63 | 64 | $paymentMock = $this->getMockBuilder(Payment::class) 65 | ->disableOriginalConstructor() 66 | ->getMock(); 67 | 68 | $paymentDataObject->expects(static::once()) 69 | ->method('getPayment') 70 | ->willReturn($paymentMock); 71 | 72 | $paymentMock->expects(static::once()) 73 | ->method('getAmountPaid') 74 | ->willReturn(1.00); 75 | 76 | $voidHandler = new CanVoidHandler($subjectReader); 77 | 78 | $this->assertFalse($voidHandler->handle($subject)); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Test/Unit/Gateway/Helper/PriceFormatterTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | 3 | namespace Pmclain\Stripe\Test\Unit\Gateway\Helper; 4 | 5 | use PHPUnit\Framework\TestCase; 6 | use Pmclain\Stripe\Gateway\Helper\PriceFormatter; 7 | use Pmclain\Stripe\Gateway\Config\Config; 8 | 9 | class PriceFormatterTest extends TestCase 10 | { 11 | /** 12 | * @var Config|\PHPUnit_Framework_MockObject_MockObject 13 | */ 14 | private $configMock; 15 | 16 | /** 17 | * @var PriceFormatter 18 | */ 19 | private $priceFormatter; 20 | 21 | protected function setUp() 22 | { 23 | $this->configMock = $this->createMock(Config::class); 24 | 25 | $this->priceFormatter = new PriceFormatter($this->configMock); 26 | } 27 | 28 | /** 29 | * @dataProvider formatPriceDataProvider 30 | * @param string $expected 31 | * @param string $price 32 | * @param string $currency 33 | */ 34 | public function testFormatPrice($expected, $price, $currency) 35 | { 36 | $this->configMock->method('getCurrency')->willReturn($currency); 37 | 38 | $this->assertEquals($expected, $this->priceFormatter->formatPrice($price)); 39 | } 40 | 41 | public function formatPriceDataProvider() 42 | { 43 | return [ 44 | [ 45 | '123', '123', 'JPY', 46 | ], 47 | [ 48 | '12300', '123', 'USD', 49 | ] 50 | ]; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Test/Unit/Gateway/Helper/SubjectReaderTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | 17 | namespace Pmclain\Stripe\Test\Unit\Gateway\Helper; 18 | 19 | use InvalidArgumentException; 20 | use Pmclain\Stripe\Gateway\Helper\SubjectReader; 21 | use Stripe\Error\Card; 22 | use Stripe\Charge; 23 | 24 | class SubjectReaderTest extends \PHPUnit\Framework\TestCase 25 | { 26 | /** 27 | * @var SubjectReader 28 | */ 29 | private $subjectReader; 30 | 31 | /** 32 | * @var Card|\PHPUnit_Framework_MockObject_MockObject 33 | */ 34 | private $cardErrorMock; 35 | 36 | /** 37 | * @var Charge|\PHPUnit_Framework_MockObject_MockObject 38 | */ 39 | private $chargeMock; 40 | 41 | protected function setUp() 42 | { 43 | $this->cardErrorMock = $this->createMock(Card::class); 44 | $this->chargeMock = $this->createMock(Charge::class); 45 | 46 | $this->subjectReader = new SubjectReader(); 47 | } 48 | 49 | public function testReadResponseObject() 50 | { 51 | $this->chargeMock->method('__toArray')->willReturn([]); 52 | $result = $this->subjectReader->readResponseObject([ 53 | 'response' => [ 54 | 'object' => $this->chargeMock, 55 | ], 56 | ]); 57 | 58 | $this->assertEquals([], $result); 59 | } 60 | 61 | public function testReadResponseObjectWithError() 62 | { 63 | $result = $this->subjectReader->readResponseObject([ 64 | 'response' => [ 65 | 'object' => $this->cardErrorMock, 66 | ], 67 | ]); 68 | 69 | $this->assertArrayHasKey('error', $result); 70 | $this->assertTrue($result['error']); 71 | } 72 | 73 | /** 74 | * @expectedException \InvalidArgumentException 75 | */ 76 | public function testReadResponseObjectWithException() 77 | { 78 | $this->subjectReader->readResponseObject(['response' => null]); 79 | } 80 | 81 | public function testReadTransaction() 82 | { 83 | $this->chargeMock->method('__toArray')->willReturn([]); 84 | $result = $this->subjectReader->readTransaction([ 85 | 'object' => $this->chargeMock, 86 | ]); 87 | 88 | $this->assertEquals([], $result); 89 | } 90 | 91 | /** 92 | * @expectedException \InvalidArgumentException 93 | */ 94 | public function testReadTransactionWithException() 95 | { 96 | $this->subjectReader->readTransaction(['object' => null]); 97 | } 98 | 99 | /** 100 | * @expectedException InvalidArgumentException 101 | * @expectedExceptionMessage The customerId field does not exist 102 | */ 103 | public function testReadCustomerIdWithException() 104 | { 105 | $this->subjectReader->readCustomerId([]); 106 | } 107 | 108 | public function testReadCustomerId() 109 | { 110 | $customerId = 1; 111 | $this->assertEquals( 112 | $customerId, 113 | $this->subjectReader->readCustomerId(['customer_id' => $customerId]) 114 | ); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/Test/Unit/Gateway/Http/Client/TransactionSubmitForSettlementTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | 17 | namespace Pmclain\Stripe\Test\Unit\Gateway\Http\Client; 18 | 19 | use Stripe\Charge; 20 | use Pmclain\Stripe\Gateway\Http\Client\TransactionSubmitForSettlement; 21 | use Pmclain\Stripe\Model\Adapter\StripeAdapter; 22 | use Magento\Payment\Gateway\Http\TransferInterface; 23 | use Magento\Payment\Model\Method\Logger; 24 | use Psr\Log\LoggerInterface; 25 | 26 | class TransactionSubmitForSettlementTest extends \PHPUnit\Framework\TestCase 27 | { 28 | /** 29 | * @var TransactionSubmitForSettlement 30 | */ 31 | private $client; 32 | 33 | /** 34 | * @var Logger|\PHPUnit_Framework_MockObject_MockObject 35 | */ 36 | private $logger; 37 | 38 | /** 39 | * @var StripeAdapter|\PHPUnit_Framework_MockObject_MockObject 40 | */ 41 | private $adapter; 42 | 43 | protected function setUp() 44 | { 45 | $criticalLoggerMock = $this->getMockForAbstractClass(LoggerInterface::class); 46 | $this->logger = $this->getMockBuilder(Logger::class) 47 | ->disableOriginalConstructor() 48 | ->setMethods(['debug']) 49 | ->getMock(); 50 | $this->adapter = $this->getMockBuilder(StripeAdapter::class) 51 | ->disableOriginalConstructor() 52 | ->setMethods(['submitForSettlement']) 53 | ->getMock(); 54 | 55 | $this->client = new TransactionSubmitForSettlement( 56 | $criticalLoggerMock, 57 | $this->logger, 58 | $this->adapter 59 | ); 60 | } 61 | 62 | /** 63 | * @expectedException \Magento\Payment\Gateway\Http\ClientException 64 | * @expectedExceptionMessage Transaction has been declined 65 | */ 66 | public function testPlaceRequestWithException() 67 | { 68 | $exception = new \Exception('Transaction has been declined'); 69 | $this->adapter->expects($this->once()) 70 | ->method('submitForSettlement') 71 | ->willThrowException($exception); 72 | 73 | $tranferObjectMock = $this->getTransferObjectMock(); 74 | $this->client->placeRequest($tranferObjectMock); 75 | } 76 | 77 | public function testPlaceRequest() 78 | { 79 | $data = new Charge(); 80 | $this->adapter->expects($this->once()) 81 | ->method('submitForSettlement') 82 | ->willReturn($data); 83 | 84 | $transferObjectMock = $this->getTransferObjectMock(); 85 | $response = $this->client->placeRequest($transferObjectMock); 86 | 87 | $this->assertTrue(is_object($response['object'])); 88 | $this->assertEquals(['object' => $data], $response); 89 | } 90 | 91 | private function getTransferObjectMock() 92 | { 93 | $mock = $this->createMock(TransferInterface::class); 94 | $mock->expects($this->once()) 95 | ->method('getBody') 96 | ->willReturn( 97 | [ 98 | 'transaction_id' => 'ch_19RXyy2eZvKYlo2CNU3GxOOe', 99 | 'amount' => 1.00 100 | ] 101 | ); 102 | 103 | return $mock; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/Test/Unit/Gateway/Http/TransferFactoryTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | 17 | namespace Pmclain\Stripe\Test\Unit\Gateway\Http\Client; 18 | 19 | use Pmclain\Stripe\Gateway\Http\TransferFactory; 20 | use Magento\Payment\Gateway\Http\TransferBuilder; 21 | use Magento\Payment\Gateway\Http\TransferInterface; 22 | 23 | class TransferFactoryTest extends \PHPUnit\Framework\TestCase 24 | { 25 | /** 26 | * @var TransferFactory 27 | */ 28 | private $transferFactory; 29 | 30 | /** 31 | * @var TransferFactory 32 | */ 33 | private $transferMock; 34 | 35 | /** 36 | * @var TransferBuilder|\PHPUnit_Framework_MockObject_MockObject 37 | */ 38 | private $transferBuilder; 39 | 40 | protected function setUp() 41 | { 42 | $this->transferBuilder = $this->createMock(TransferBuilder::class); 43 | $this->transferMock = $this->createMock(TransferInterface::class); 44 | 45 | $this->transferFactory = new TransferFactory($this->transferBuilder); 46 | } 47 | 48 | public function testCreate() 49 | { 50 | $request = ['data1', 'data1']; 51 | 52 | $this->transferBuilder->expects($this->once()) 53 | ->method('setBody') 54 | ->with($request) 55 | ->willReturnSelf(); 56 | 57 | $this->transferBuilder->expects($this->once()) 58 | ->method('build') 59 | ->willReturn($this->transferMock); 60 | 61 | $this->assertEquals($this->transferMock, 62 | $this->transferFactory->create($request)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Test/Unit/Gateway/Request/SettlementDataBuilderTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | 17 | namespace Pmclain\Stripe\Test\Unit\Gateway\Request; 18 | 19 | use Pmclain\Stripe\Gateway\Request\SettlementDataBuilder; 20 | 21 | class SettlementDataBuilderTest extends \PHPUnit\Framework\TestCase 22 | { 23 | public function testBuild() 24 | { 25 | $builder = new SettlementDataBuilder(); 26 | $this->assertEquals( 27 | [SettlementDataBuilder::SUBMIT_FOR_SETTLEMENT => true], 28 | $builder->build([]) 29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Test/Unit/Gateway/Request/ThreeDSecureBuilderTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | 17 | namespace Pmclain\Stripe\Test\Unit\Gateway\Request; 18 | 19 | use Pmclain\Stripe\Gateway\Config\Config; 20 | use Pmclain\Stripe\Gateway\Helper\SubjectReader; 21 | use Pmclain\Stripe\Gateway\Request\ThreeDSecureBuilder; 22 | use Magento\Payment\Gateway\Data\PaymentDataObjectInterface; 23 | use Magento\Payment\Model\InfoInterface; 24 | 25 | class ThreeDSecureBuilderTest extends \PHPUnit\Framework\TestCase 26 | { 27 | /** 28 | * @var ThreeDSecureBuilder 29 | */ 30 | private $builder; 31 | 32 | /** 33 | * @var Config|\PHPUnit_Framework_MockObject_MockObject 34 | */ 35 | private $configMock; 36 | 37 | /** 38 | * @var PaymentDataObjectInterface|\PHPUnit_Framework_MockObject_MockObject 39 | */ 40 | private $paymentDataObjectMock; 41 | 42 | /** 43 | * @var InfoInterface|\PHPUnit_Framework_MockObject_MockObject 44 | */ 45 | private $paymentMock; 46 | 47 | /** 48 | * @var SubjectReader 49 | */ 50 | private $subjectReader; 51 | 52 | protected function setUp() 53 | { 54 | $this->configMock = $this->createMock(Config::class); 55 | $this->paymentDataObjectMock = $this->createMock(PaymentDataObjectInterface::class); 56 | $this->paymentMock = $this->createMock(InfoInterface::class); 57 | $this->subjectReader = new SubjectReader(); 58 | 59 | $this->paymentDataObjectMock->method('getPayment')->willReturn($this->paymentMock); 60 | 61 | $this->builder = new ThreeDSecureBuilder($this->configMock, $this->subjectReader); 62 | } 63 | 64 | public function testBuildDisabled() 65 | { 66 | $this->configMock->method('isRequireThreeDSecure')->willReturn(false); 67 | $this->assertEquals([], $this->builder->build([])); 68 | } 69 | 70 | public function testBuildBelowThreshold() 71 | { 72 | $this->configMock->method('isRequireThreeDSecure')->willReturn(true); 73 | $this->configMock->method('getThreeDSecureThreshold')->willReturn(2.00); 74 | 75 | $subject = [ 76 | 'amount' => 1.00, 77 | ]; 78 | 79 | $this->assertEquals([], $this->builder->build($subject)); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Test/Unit/Gateway/Request/VoidDataBuilderTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | 17 | namespace Pmclain\Stripe\Test\Unit\Gateway\Request; 18 | 19 | use Pmclain\Stripe\Gateway\Request\VoidDataBuilder; 20 | use Pmclain\Stripe\Gateway\Helper\SubjectReader; 21 | use Magento\Payment\Gateway\Data\PaymentDataObjectInterface; 22 | use Magento\Sales\Model\Order\Payment; 23 | 24 | class VoidDataBuilderTest extends \PHPUnit\Framework\TestCase 25 | { 26 | /** 27 | * @var VoidDataBuilder 28 | */ 29 | private $builder; 30 | 31 | /** 32 | * @var SubjectReader|\PHPUnit_Framework_MockObject_MockObject 33 | */ 34 | private $subjectReader; 35 | 36 | protected function setUp() 37 | { 38 | $this->subjectReader = $this->getMockBuilder(SubjectReader::class) 39 | ->disableOriginalConstructor() 40 | ->getMock(); 41 | 42 | $this->builder = new VoidDataBuilder($this->subjectReader); 43 | } 44 | 45 | /** 46 | * 47 | * @dataProvider testBuildDataProvider 48 | */ 49 | public function testBuild($parentTransId, $lastTransId) 50 | { 51 | $paymentDataObject = $this->createMock(PaymentDataObjectInterface::class); 52 | $buildSubject = ['payment' => $paymentDataObject]; 53 | $paymentMock = $this->getMockBuilder(Payment::class) 54 | ->disableOriginalConstructor() 55 | ->getMock(); 56 | 57 | $this->subjectReader->expects($this->once()) 58 | ->method('readPayment') 59 | ->with($buildSubject) 60 | ->willReturn($paymentDataObject); 61 | $paymentDataObject->expects($this->once()) 62 | ->method('getPayment') 63 | ->willReturn($paymentMock); 64 | $paymentMock->expects($this->once()) 65 | ->method('getParentTransactionId') 66 | ->willReturn($parentTransId); 67 | if (!$parentTransId) { 68 | $paymentMock->expects($this->once()) 69 | ->method('getLastTransId') 70 | ->willReturn($lastTransId); 71 | } 72 | 73 | $this->assertEquals( 74 | ['transaction_id' => $parentTransId ?: $lastTransId], 75 | $this->builder->build($buildSubject) 76 | ); 77 | } 78 | 79 | public function testBuildDataProvider() 80 | { 81 | return [ 82 | ['ch_19RZmz2eZvKYlo2CktQObIT0', null], 83 | [false, 'ch_19RZmz2eZvKYlo2CktQObIT0'] 84 | ]; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Test/Unit/Gateway/Response/RefundHandlerTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | 17 | namespace Pmclain\Stripe\Test\Unit\Gateway\Response; 18 | 19 | use Pmclain\Stripe\Gateway\Response\RefundHandler; 20 | use Magento\Sales\Model\Order\Payment; 21 | use Magento\Sales\Model\Order\Creditmemo; 22 | use Magento\Sales\Model\Order\Invoice; 23 | use Pmclain\Stripe\Gateway\Helper\SubjectReader; 24 | 25 | class RefundHandlerTest extends \PHPUnit\Framework\TestCase 26 | { 27 | public function testShouldCloseParentTransaction() 28 | { 29 | $subjectReader = $this->getMockBuilder(SubjectReader::class) 30 | ->disableOriginalConstructor() 31 | ->getMock(); 32 | $payment = $this->getMockBuilder(Payment::class) 33 | ->disableOriginalConstructor() 34 | ->setMethods(['getCreditmemo']) 35 | ->getMock(); 36 | $creditmemo = $this->getMockBuilder(Creditmemo::class) 37 | ->disableOriginalConstructor() 38 | ->setMethods(['getInvoice']) 39 | ->getMock(); 40 | $invoice = $this->getMockBuilder(Invoice::class) 41 | ->disableOriginalConstructor() 42 | ->setMethods(['canRefund']) 43 | ->getMock(); 44 | 45 | $invoice->expects($this->once()) 46 | ->method('canRefund') 47 | ->willReturn(true); 48 | $creditmemo->expects($this->once()) 49 | ->method('getInvoice') 50 | ->willReturn($invoice); 51 | $payment->expects($this->once()) 52 | ->method('getCreditmemo') 53 | ->willReturn($creditmemo); 54 | 55 | $handler = new RefundHandler($subjectReader); 56 | $reflection = new \ReflectionClass(get_class($handler)); 57 | $method = $reflection->getMethod('shouldCloseParentTransaction'); 58 | $method->setAccessible(true); 59 | 60 | $this->assertFalse($method->invokeArgs($handler, [$payment])); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Test/Unit/Gateway/Response/TransactionHandlerTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | 17 | namespace Pmclain\Stripe\Test\Unit\Gateway\Response; 18 | 19 | use Pmclain\Stripe\Gateway\Response\TransactionIdHandler; 20 | use Pmclain\Stripe\Gateway\Helper\SubjectReader; 21 | use Magento\Payment\Gateway\Data\PaymentDataObjectInterface; 22 | use Magento\Sales\Model\Order\Payment; 23 | 24 | class TransactionHandlerTest extends \PHPUnit\Framework\TestCase 25 | { 26 | public function testHandle() 27 | { 28 | $transactionId = 'ch_19Rjix2eZvKYlo2C5VFbcuXf'; 29 | $paymentDataObject = $this->createMock(PaymentDataObjectInterface::class); 30 | $paymentInfo = $this->getMockBuilder(Payment::class) 31 | ->disableOriginalConstructor() 32 | ->getMock(); 33 | 34 | $subject = ['payment' => $paymentDataObject]; 35 | $response = ['object' => ['id' => $transactionId]]; 36 | 37 | $subjectReader = $this->getMockBuilder(SubjectReader::class) 38 | ->disableOriginalConstructor() 39 | ->getMock(); 40 | 41 | $subjectReader->expects($this->once()) 42 | ->method('readPayment') 43 | ->with($subject) 44 | ->willReturn($paymentDataObject); 45 | $paymentDataObject->expects($this->atLeastOnce()) 46 | ->method('getPayment') 47 | ->willReturn($paymentInfo); 48 | $subjectReader->expects($this->once()) 49 | ->method('readTransaction') 50 | ->with($response) 51 | ->willReturn($response['object']); 52 | $paymentInfo->expects($this->once()) 53 | ->method('setTransactionId') 54 | ->with($transactionId); 55 | $paymentInfo->expects($this->once()) 56 | ->method('setIsTransactionClosed') 57 | ->with(false); 58 | $paymentInfo->expects($this->once()) 59 | ->method('setShouldCloseParentTransaction') 60 | ->with(false); 61 | 62 | $handler = new TransactionIdHandler($subjectReader); 63 | $handler->handle($subject, $response); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Test/Unit/Gateway/Response/VoidHandlerTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | 17 | namespace Pmclain\Stripe\Test\Unit\Gateway\Response; 18 | 19 | use Pmclain\Stripe\Gateway\Helper\SubjectReader; 20 | use Pmclain\Stripe\Gateway\Response\VoidHandler; 21 | use Magento\Payment\Gateway\Data\PaymentDataObjectInterface; 22 | use Magento\Sales\Model\Order\Payment; 23 | 24 | class VoidHandlerTest extends \PHPUnit\Framework\TestCase 25 | { 26 | public function testHandle() 27 | { 28 | $transactionId = 'ch_19Rjix2eZvKYlo2C5VFbcuXf'; 29 | $paymentDataObject = $this->createMock(PaymentDataObjectInterface::class); 30 | $payment = $this->getMockBuilder(Payment::class) 31 | ->disableOriginalConstructor() 32 | ->getMock(); 33 | $subject = ['payment' => $paymentDataObject]; 34 | $response = ['object' => ['id' => $transactionId]]; 35 | 36 | $subjectReader = $this->getMockBuilder(SubjectReader::class) 37 | ->disableOriginalConstructor() 38 | ->getMock(); 39 | 40 | $subjectReader->expects($this->once()) 41 | ->method('readPayment') 42 | ->with($subject) 43 | ->willReturn($paymentDataObject); 44 | $paymentDataObject->expects($this->atLeastOnce()) 45 | ->method('getPayment') 46 | ->willReturn($payment); 47 | $subjectReader->expects($this->once()) 48 | ->method('readTransaction') 49 | ->with($response) 50 | ->willReturn($response['object']); 51 | $payment->expects($this->never()) 52 | ->method('setTransactionId'); 53 | $payment->expects($this->once()) 54 | ->method('setIsTransactionClosed') 55 | ->with(true); 56 | $payment->expects($this->once()) 57 | ->method('setShouldCloseParentTransaction') 58 | ->with(true); 59 | 60 | $handler = new VoidHandler($subjectReader); 61 | $handler->handle($subject, $response); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Test/Unit/Helper/CcTypeTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | /** 3 | * Pmclain_Stripe extension 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the OSL 3.0 License 7 | * that is bundled with this package in the file LICENSE.txt. 8 | * It is also available through the world-wide-web at this URL: 9 | * https://opensource.org/licenses/osl-3.0.php 10 | * 11 | * @category Pmclain 12 | * @package Pmclain_Stripe 13 | * @copyright Copyright (c) 2017-2018 14 | * @license Open Software License (OSL 3.0) 15 | */ 16 | 17 | namespace Pmclain\Stripe\Test\Unit\Helper; 18 | 19 | use Pmclain\Stripe\Model\Adminhtml\Source\Cctype as CcTypeSource; 20 | use Pmclain\Stripe\Helper\CcType; 21 | use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; 22 | 23 | class CcTypeTest extends \PHPUnit\Framework\TestCase 24 | { 25 | /** @var ObjectManager */ 26 | private $objectManager; 27 | 28 | /** @var CcType */ 29 | private $helper; 30 | 31 | /** @var CcTypeSource|\PHPUnit_Framework_MockObject_MockObject */ 32 | private $ccTypeSource; 33 | 34 | protected function setUp() 35 | { 36 | $this->objectManager = new ObjectManager($this); 37 | 38 | $this->ccTypeSource = $this->getMockBuilder(CcTypeSource::class) 39 | ->disableOriginalConstructor() 40 | ->setMethods(['toOptionArray']) 41 | ->getMock(); 42 | 43 | $this->helper = $this->objectManager->getObject( 44 | CcType::class, 45 | ['ccTypeSource' => $this->ccTypeSource] 46 | ); 47 | } 48 | 49 | public function testGetCcTypes() 50 | { 51 | $this->ccTypeSource->expects($this->once()) 52 | ->method('toOptionArray') 53 | ->willReturn([ 54 | 'label' => 'Visa', 55 | 'value' => 'VI' 56 | ]); 57 | $this->helper->getCcTypes(); 58 | $this->ccTypeSource->expects($this->never()) 59 | ->method('toOptionArray'); 60 | $this->helper->getCcTypes(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Test/Unit/Model/InstantPurchase/CreditCard/TokenFormatterTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | 3 | namespace Pmclain\Stripe\Test\Unit\Model\InstantPurchase\CreditCard; 4 | 5 | use Magento\Vault\Api\Data\PaymentTokenInterface; 6 | use PHPUnit\Framework\TestCase; 7 | use Pmclain\Stripe\Model\InstantPurchase\CreditCard\TokenFormatter; 8 | 9 | class TokenFormatterTest extends TestCase 10 | { 11 | /** 12 | * @var PaymentTokenInterface|\PHPUnit_Framework_MockObject_MockObject 13 | */ 14 | private $paymentTokenMock; 15 | 16 | /** 17 | * @var TokenFormatter 18 | */ 19 | private $model; 20 | 21 | public function setUp() 22 | { 23 | $this->paymentTokenMock = $this->createMock(PaymentTokenInterface::class); 24 | 25 | $this->model = new TokenFormatter(); 26 | } 27 | 28 | public function testFormatPaymentToken() 29 | { 30 | $this->paymentTokenMock->method('getTokenDetails')->willReturn(json_encode([ 31 | 'type' => 'AE', 32 | 'maskedCC' => '4444', 33 | 'expirationDate' => '12/29' 34 | ])); 35 | 36 | $this->assertEquals( 37 | 'Credit Card: American Express, ending: 4444 (expires: 12/29)', 38 | $this->model->formatPaymentToken($this->paymentTokenMock) 39 | ); 40 | } 41 | 42 | /** 43 | * @expectedException \InvalidArgumentException 44 | */ 45 | public function testFormatPaymentTokenException() 46 | { 47 | $this->model->formatPaymentToken($this->paymentTokenMock); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Test/Unit/Model/Ui/Adminhtml/TokenUiComponentProviderTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | 3 | namespace Pmclain\Stripe\Test\Unit\Model\Ui\Adminhtml; 4 | 5 | use PHPUnit\Framework\TestCase; 6 | use Pmclain\Stripe\Model\Ui\Adminhtml\TokenUiComponentProvider; 7 | use Magento\Framework\UrlInterface; 8 | use Magento\Framework\Json\Decoder; 9 | use Magento\Vault\Model\Ui\TokenUiComponentInterfaceFactory; 10 | use Magento\Vault\Model\Ui\TokenUiComponentInterface; 11 | use Magento\Vault\Api\Data\PaymentTokenInterface; 12 | 13 | class TokenUiComponentProviderTest extends TestCase 14 | { 15 | /** 16 | * @var TokenUiComponentInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject 17 | */ 18 | private $componentFactoryMock; 19 | 20 | /** 21 | * @var TokenUiComponentInterface|\PHPUnit_Framework_MockObject_MockObject 22 | */ 23 | private $componentMock; 24 | 25 | /** 26 | * @var UrlInterface|\PHPUnit_Framework_MockObject_MockObject 27 | */ 28 | private $urlMock; 29 | 30 | /** 31 | * @var PaymentTokenInterface|\PHPUnit_Framework_MockObject_MockObject 32 | */ 33 | private $paymentTokenMock; 34 | 35 | /** 36 | * @var TokenUiComponentProvider 37 | */ 38 | private $model; 39 | 40 | protected function setUp() 41 | { 42 | $this->componentFactoryMock = $this->createMock(TokenUiComponentInterfaceFactory::class); 43 | $this->componentMock = $this->createMock(TokenUiComponentInterface::class); 44 | $this->urlMock = $this->createMock(UrlInterface::class); 45 | $this->paymentTokenMock = $this->createMock(PaymentTokenInterface::class); 46 | 47 | $this->componentFactoryMock->method('create')->willReturn($this->componentMock); 48 | 49 | $this->model = new TokenUiComponentProvider( 50 | $this->componentFactoryMock, 51 | $this->urlMock, 52 | new Decoder() 53 | ); 54 | } 55 | 56 | public function testGetComponentForToken() 57 | { 58 | $this->assertInstanceOf( 59 | TokenUiComponentInterface::class, 60 | $this->model->getComponentForToken($this->paymentTokenMock) 61 | ); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Test/Unit/Model/Ui/ConfigProviderTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | 3 | namespace Pmclain\Stripe\Test\Unit\Model\Ui; 4 | 5 | use Magento\Framework\App\Config\ScopeConfigInterface; 6 | use PHPUnit\Framework\TestCase; 7 | use Magento\Framework\UrlInterface; 8 | use Pmclain\Stripe\Model\Ui\ConfigProvider; 9 | 10 | class ConfigProviderTest extends TestCase 11 | { 12 | /** 13 | * @var UrlInterface|\PHPUnit_Framework_MockObject_MockObject 14 | */ 15 | private $urlMock; 16 | 17 | /** 18 | * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject 19 | */ 20 | private $configMock; 21 | 22 | /** 23 | * @var ConfigProvider 24 | */ 25 | private $model; 26 | 27 | protected function setUp() 28 | { 29 | $this->urlMock = $this->createMock(UrlInterface::class); 30 | $this->configMock = $this->createMock(ScopeConfigInterface::class); 31 | 32 | $this->model = new ConfigProvider( 33 | $this->configMock, 34 | $this->urlMock 35 | ); 36 | } 37 | 38 | public function testGetConfig() 39 | { 40 | $config = $this->model->getConfig(); 41 | $this->assertArrayHasKey(ConfigProvider::CODE, $config['payment']); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Test/Unit/Model/Ui/TokenUiComponentProviderTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | 3 | namespace Pmclain\Stripe\Test\Unit\Model\Ui; 4 | 5 | use PHPUnit\Framework\TestCase; 6 | use Pmclain\Stripe\Gateway\Config\Config; 7 | use Pmclain\Stripe\Model\Ui\TokenUiComponentProvider; 8 | use Magento\Framework\UrlInterface; 9 | use Magento\Framework\Json\Decoder; 10 | use Magento\Vault\Model\Ui\TokenUiComponentInterfaceFactory; 11 | use Magento\Vault\Model\Ui\TokenUiComponentInterface; 12 | use Magento\Vault\Api\Data\PaymentTokenInterface; 13 | 14 | class TokenUiComponentProviderTest extends TestCase 15 | { 16 | /** 17 | * @var TokenUiComponentInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject 18 | */ 19 | private $componentFactoryMock; 20 | 21 | /** 22 | * @var TokenUiComponentInterface|\PHPUnit_Framework_MockObject_MockObject 23 | */ 24 | private $componentMock; 25 | 26 | /** 27 | * @var UrlInterface|\PHPUnit_Framework_MockObject_MockObject 28 | */ 29 | private $urlMock; 30 | 31 | /** 32 | * @var Config|\PHPUnit_Framework_MockObject_MockObject 33 | */ 34 | private $configMock; 35 | 36 | /** 37 | * @var PaymentTokenInterface|\PHPUnit_Framework_MockObject_MockObject 38 | */ 39 | private $paymentTokenMock; 40 | 41 | /** 42 | * @var TokenUiComponentProvider 43 | */ 44 | private $model; 45 | 46 | protected function setUp() 47 | { 48 | $this->componentFactoryMock = $this->createMock(TokenUiComponentInterfaceFactory::class); 49 | $this->componentMock = $this->createMock(TokenUiComponentInterface::class); 50 | $this->urlMock = $this->createMock(UrlInterface::class); 51 | $this->configMock = $this->createMock(Config::class); 52 | $this->paymentTokenMock = $this->createMock(PaymentTokenInterface::class); 53 | 54 | $this->componentFactoryMock->method('create')->willReturn($this->componentMock); 55 | 56 | $this->model = new TokenUiComponentProvider( 57 | $this->componentFactoryMock, 58 | $this->urlMock, 59 | new Decoder(), 60 | $this->configMock 61 | ); 62 | } 63 | 64 | public function testGetComponentForToken() 65 | { 66 | $this->assertInstanceOf( 67 | TokenUiComponentInterface::class, 68 | $this->model->getComponentForToken($this->paymentTokenMock) 69 | ); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Test/Unit/Observer/DataAssignObserverTest.php: -------------------------------------------------------------------------------- 1 | <?php 2 | 3 | namespace Pmclain\Stripe\Test\Unit\Observer; 4 | 5 | use Magento\Framework\DataObject; 6 | use PHPUnit\Framework\TestCase; 7 | use PHPUnit_Framework_MockObject_MockObject as MockObject; 8 | use Pmclain\Stripe\Observer\DataAssignObserver; 9 | use Magento\Quote\Model\Quote\Payment; 10 | use Magento\Framework\Event\Observer; 11 | use Magento\Framework\Event; 12 | 13 | class DataAssignObserverTest extends TestCase 14 | { 15 | /** 16 | * @var DataObject 17 | */ 18 | private $data; 19 | 20 | /** 21 | * @var Payment|MockObject 22 | */ 23 | private $paymentMock; 24 | 25 | /** 26 | * @var Observer|MockObject 27 | */ 28 | private $observer; 29 | 30 | /** 31 | * @var Event|MockObject 32 | */ 33 | private $event; 34 | 35 | /** 36 | * @var DataAssignObserver 37 | */ 38 | private $dataAssigner; 39 | 40 | protected function setUp() 41 | { 42 | $this->paymentMock = $this->createMock(Payment::class); 43 | 44 | $this->data = new DataObject([ 45 | 'additional_data' => [ 46 | 'cc_exp_month' => '12', 47 | 'cc_exp_year' => '2022', 48 | 'cc_last4' => '1111', 49 | 'cc_type' => 'Visa', 50 | 'cc_token' => 'tkn_123', 51 | 'cc_src' => 'crd_123', 52 | 'three_d_src' => 'tds_123', 53 | 'three_d_client_secret' => 'client_secret', 54 | ], 55 | ]); 56 | 57 | $this->event = new Event([ 58 | 'data' => $this->data, 59 | ]); 60 | 61 | $this->observer = new Observer([ 62 | 'event' => $this->event, 63 | 'payment_model' => $this->paymentMock, 64 | ]); 65 | 66 | $this->dataAssigner = new DataAssignObserver(); 67 | } 68 | 69 | public function testExecute() 70 | { 71 | $this->paymentMock->expects($this->exactly(4)) 72 | ->method('setAdditionalInformation'); 73 | 74 | $this->dataAssigner->execute($this->observer); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Test/Unit/phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="UTF-8"?> 2 | <!-- 3 | /** 4 | * Copyright © Magento, Inc. All rights reserved. 5 | * See COPYING.txt for license details. 6 | */ 7 | --> 8 | <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 9 | xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.2/phpunit.xsd" 10 | colors="true" 11 | beStrictAboutTestsThatDoNotTestAnything="false" 12 | bootstrap="./framework/bootstrap.php" 13 | > 14 | <!-- Test suites definition --> 15 | <testsuites> 16 | <testsuite name="Pmclain Stripe Unit Tests"> 17 | <directory suffix="Test.php">../../../vendor/pmclain/module-stripe/src/Test/Unit</directory> 18 | </testsuite> 19 | </testsuites> 20 | <php> 21 | <ini name="date.timezone" value="America/Los_Angeles"/> 22 | <ini name="xdebug.max_nesting_level" value="200"/> 23 | </php> 24 | <filter> 25 | <whitelist addUncoveredFilesFromWhiteList="true"> 26 | <directory suffix=".php">../../../vendor/pmclain/module-stripe/src</directory> 27 | <exclude> 28 | <directory>../../../vendor/pmclain/module-stripe/src/Test</directory> 29 | </exclude> 30 | </whitelist> 31 | </filter> 32 | <listeners> 33 | <listener class="Magento\Framework\TestFramework\Unit\Listener\ReplaceObjectManager"/> 34 | </listeners> 35 | <logging> 36 | <log type="coverage-clover" target="coverage/clover.xml"/> 37 | </logging> 38 | </phpunit> 39 | -------------------------------------------------------------------------------- /src/etc/adminhtml/di.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" ?> 2 | <!-- 3 | /** 4 | * Pmclain_Stripe extension 5 | * NOTICE OF LICENSE 6 | * 7 | * This source file is subject to the OSL 3.0 License 8 | * that is bundled with this package in the file LICENSE.txt. 9 | * It is also available through the world-wide-web at this URL: 10 | * https://opensource.org/licenses/osl-3.0.php 11 | * 12 | * @category Pmclain 13 | * @package Pmclain_Stripe 14 | * @copyright Copyright (c) 2017-2018 15 | * @license Open Software License (OSL 3.0) 16 | */ 17 | --> 18 | <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> 19 | <type name="Pmclain\Stripe\Block\Info"> 20 | <arguments> 21 | <argument name="data" xsi:type="array"> 22 | <item xsi:type="string" name="is_secure_mode">0</item> 23 | </argument> 24 | </arguments> 25 | </type> 26 | <type name="Magento\Vault\Model\Ui\Adminhtml\TokensConfigProvider"> 27 | <arguments> 28 | <argument name="tokenUiComponentProviders" xsi:type="array"> 29 | <item name="pmclain_stripe" xsi:type="object">Pmclain\Stripe\Model\Ui\Adminhtml\TokenUiComponentProvider</item> 30 | </argument> 31 | </arguments> 32 | </type> 33 | 34 | <!-- Admin Payment Config --> 35 | <virtualType name="StripeVaultAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite"> 36 | <arguments> 37 | <argument name="builders" xsi:type="array"> 38 | <item name="payment" xsi:type="string">Pmclain\Stripe\Gateway\Request\PaymentDataBuilder\Vault\Admin</item> 39 | <item name="address" xsi:type="string">Pmclain\Stripe\Gateway\Request\AddressDataBuilder</item> 40 | </argument> 41 | </arguments> 42 | </virtualType> 43 | <virtualType name="StripeAuthorizeRequest" type="Magento\Payment\Gateway\Request\BuilderComposite"> 44 | <arguments> 45 | <argument name="builders" xsi:type="array"> 46 | <item name="payment" xsi:type="string">Pmclain\Stripe\Gateway\Request\PaymentDataBuilder\Admin</item> 47 | <item name="address" xsi:type="string">Pmclain\Stripe\Gateway\Request\AddressDataBuilder</item> 48 | <!--<item name="vault" xsi:type="string">Pmclain\Stripe\Gateway\Request\VaultDataBuilder</item>--> 49 | </argument> 50 | </arguments> 51 | </virtualType> 52 | </config> -------------------------------------------------------------------------------- /src/etc/config.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" ?> 2 | <!-- 3 | /** 4 | * Pmclain_Stripe extension 5 | * NOTICE OF LICENSE 6 | * 7 | * This source file is subject to the OSL 3.0 License 8 | * that is bundled with this package in the file LICENSE.txt. 9 | * It is also available through the world-wide-web at this URL: 10 | * https://opensource.org/licenses/osl-3.0.php 11 | * 12 | * @category Pmclain 13 | * @package Pmclain_Stripe 14 | * @copyright Copyright (c) 2017-2018 15 | * @license Open Software License (OSL 3.0) 16 | */ 17 | --> 18 | <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd"> 19 | <default> 20 | <payment> 21 | <pmclain_stripe> 22 | <model>StripeFacade</model> 23 | <payment_action>authorize</payment_action> 24 | <active>0</active> 25 | <title>Stripe Credit Card 26 | 1 27 | 1 28 | 1 29 | 1 30 | 1 31 | 1 32 | 1 33 | 1 34 | 1 35 | 1 36 | 1 37 | 1 38 | 1 39 | 1 40 | 1 41 | AE,VI,MC,DI,JCB,CUP,DN,MI 42 | 1 43 | 44 | processing 45 | 0 46 | USD 47 | 1 48 | 49 | 50 | 51 | 52 | 0 53 | 0.00 54 | 55 | 56 | StripeCreditCardVaultFacade 57 | Stored Cards (Stripe) 58 | 1 59 | 60 | 1 61 | Pmclain\Stripe\Model\InstantPurchase\CreditCard\TokenFormatter 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/etc/events.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/etc/frontend/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | Pmclain\Stripe\Model\Ui\ConfigProvider 23 | 24 | 25 | 26 | 27 | 28 | 29 | 1 30 | 31 | 32 | 33 | 34 | 35 | 36 | Pmclain\Stripe\Model\Ui\ConfigProvider::CODE 37 | 38 | 39 | 40 | 41 | 42 | 43 | Pmclain\Stripe\Model\Ui\TokenUiComponentProvider 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/etc/frontend/routes.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/registration.php: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | pmclain_stripe 23 | Pmclain_Stripe::form/cc.phtml 24 | 25 | 26 | 27 | 28 | pmclain_stripe_vault 29 | Magento_Vault::form/vault.phtml 30 | 31 | 32 | 33 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/view/adminhtml/layout/sales_order_create_load_block_billing_method.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | pmclain_stripe 23 | Pmclain_Stripe::form/cc.phtml 24 | 25 | 26 | 27 | 28 | pmclain_stripe_vault 29 | Magento_Vault::form/vault.phtml 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/view/adminhtml/templates/form/cc.phtml: -------------------------------------------------------------------------------- 1 | escapeHtml($block->getMethodCode()); 20 | $ccType = $block->getInfoData('cc_type'); 21 | $ccExpMonth = $block->getInfoData('cc_exp_month'); 22 | $ccExpYear = $block->getInfoData('cc_exp_year'); 23 | ?> 24 | 47 | -------------------------------------------------------------------------------- /src/view/adminhtml/templates/form/vault.phtml: -------------------------------------------------------------------------------- 1 | getData(TokenUiComponentProviderInterface::COMPONENT_DETAILS); 20 | $icon = $block->getData('icons')[$details['type']]; 21 | $id = $block->escapeHtml($block->getData('id')); 22 | ?> 23 |
", 28 | "nonceUrl": "escapeUrl($block->getData('nonceUrl')); ?>" 29 | } 30 | }' id="payment_" class="admin__field"> 31 |
32 | 33 | 37 | escapeHtml(__('ending'));?> 38 | escapeHtml($details['maskedCC']); ?> 39 | (escapeHtml(__('expires'));?>: 40 | escapeHtml($details['expirationDate']); ?>) 41 |
42 |
43 | -------------------------------------------------------------------------------- /src/view/adminhtml/templates/payment/script.phtml: -------------------------------------------------------------------------------- 1 | escapeHtml($block->getCode()); 20 | ?> 21 | 38 | -------------------------------------------------------------------------------- /src/view/adminhtml/web/js/vault.js: -------------------------------------------------------------------------------- 1 | define([ 2 | 'jquery', 3 | 'uiComponent' 4 | ], function ($, Class) { 5 | 'use strict'; 6 | 7 | return Class.extend({ 8 | defaults: { 9 | $selector: null, 10 | selector: 'edit_form' 11 | }, 12 | 13 | initObservable: function () { 14 | var self = this; 15 | 16 | self.$selector = $('#' + self.selector); 17 | this._super(); 18 | 19 | this.initEventHandlers(); 20 | 21 | return this; 22 | }, 23 | 24 | getCode: function () { 25 | return this.code; 26 | }, 27 | 28 | initEventHandlers: function () { 29 | $('#' + this.container).find('[name="payment[token_switcher]"]') 30 | .on('click', this.setPaymentDetails.bind(this)); 31 | }, 32 | 33 | setPaymentDetails: function () { 34 | this.$selector.find('[name="payment[public_hash]"]').val(this.publicHash); 35 | } 36 | }); 37 | }); -------------------------------------------------------------------------------- /src/view/frontend/layout/checkout_index_index.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | uiComponent 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | Pmclain_Stripe/js/view/payment/pmclain_stripe 38 | 39 | 40 | true 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/view/frontend/layout/vault_cards_listaction.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/view/frontend/web/js/action/save-payment-information.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @api 3 | */ 4 | define([ 5 | 'Magento_Checkout/js/model/quote', 6 | 'Magento_Checkout/js/model/url-builder', 7 | 'Magento_Customer/js/model/customer', 8 | 'Pmclain_Stripe/js/model/save-payment-information' 9 | ], function (quote, urlBuilder, customer, savePaymentService) { 10 | 'use strict'; 11 | 12 | return function (paymentData, messageContainer) { 13 | var serviceUrl, payload; 14 | 15 | payload = { 16 | cartId: quote.getQuoteId(), 17 | billingAddress: quote.billingAddress(), 18 | paymentMethod: paymentData 19 | }; 20 | 21 | if (customer.isLoggedIn()) { 22 | serviceUrl = urlBuilder.createUrl('/carts/mine/set-payment-information', {}); 23 | } else { 24 | serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/set-payment-information', { 25 | quoteId: quote.getQuoteId() 26 | }); 27 | payload.email = quote.guestEmail; 28 | } 29 | 30 | return savePaymentService(serviceUrl, payload, messageContainer); 31 | }; 32 | }); 33 | -------------------------------------------------------------------------------- /src/view/frontend/web/js/model/save-payment-information.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @api 3 | */ 4 | define( 5 | [ 6 | 'mage/storage', 7 | 'Magento_Checkout/js/model/error-processor', 8 | 'Magento_Checkout/js/model/full-screen-loader' 9 | ], 10 | function (storage, errorProcessor, fullScreenLoader) { 11 | 'use strict'; 12 | 13 | return function (serviceUrl, payload, messageContainer) { 14 | fullScreenLoader.startLoader(); 15 | 16 | return storage.post( 17 | serviceUrl, JSON.stringify(payload) 18 | ).fail( 19 | function (response) { 20 | errorProcessor.process(response, messageContainer); 21 | } 22 | ).always( 23 | function () { 24 | fullScreenLoader.stopLoader(); 25 | } 26 | ); 27 | }; 28 | } 29 | ); 30 | -------------------------------------------------------------------------------- /src/view/frontend/web/js/view/payment/pmclain_stripe.js: -------------------------------------------------------------------------------- 1 | define( 2 | [ 3 | 'uiComponent', 4 | 'Magento_Checkout/js/model/payment/renderer-list' 5 | ], 6 | function ( 7 | Component, 8 | rendererList 9 | ) { 10 | 'use strict'; 11 | rendererList.push( 12 | { 13 | type: 'pmclain_stripe', 14 | component: 'Pmclain_Stripe/js/view/payment/method-renderer/pmclain_stripe' 15 | } 16 | ); 17 | /** Add view logic here if needed */ 18 | return Component.extend({}); 19 | } 20 | ); -------------------------------------------------------------------------------- /src/view/frontend/web/template/payment/form.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 7 | 8 |
9 |
10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 |
18 | 19 |
20 |
21 | 22 |
23 | 24 |
25 | 29 | 32 |
33 | 34 |
35 | 36 |
37 | 38 | 39 | 40 |
41 |
42 |
43 | 54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------