Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

Stripe v3 module for SCA


asro2004

Recommended Posts

I have created a fork of the standard Stripe payments module to provide support for SCA. I tried uploading it to the market place, but it does not seem to be accepting it.

A copy of the zip is attached.

Stripe SCA Payment module

Stripe SCA is a refactored version of the standard Stripe payments to update the Stripe API to v3 and support the SCA process flow. Other than using different Stripe API calls to set up and process payments, the main change is to defer order fulfillment to a web hook called by Stripe after the payment has been authorised.

This module is installed as a separate payment method from the standard Stripe module and can be run in parallel.

Note that it shares the customer_stripe_tokens table created by the standard Stripe module, and cards saved using the standard Stripe module can be reused by the Stripe SCA module, however, cards stored by the Stripe SCA module cannot be reused by the standard Stripe module. They will be rejected by Stripe with a message 'You cannot create a charge with a PaymentMethod. Use the Payment Intents API instead.'

Install

Copy the contents of this zip to the root osCommerce folder of your store.

Login to the osCommerce Admin page of your store and go to Modules > Payment.
- Click on the Install button at the upper right of the page
- Choose 'Stripe SCA' from the module list and select Install Module.

If you are allowing cards to be saved, add the cards management page:
- go to Modules > Content
- click on the Install Module button at the upper right of the page
- select 'Stripe SCA Cards Management Page' and select Install Module.
That will add the 'Manage saved payment cards' link to the customers' My Account page.

Configuration

The basic configuration of the Stripe SCA module is the same as the standard Stripe module, requiring Publishable and Secret API keys, however as the order fulfillment has been moved to a webhook, you need to add the address of the Stripe SCA webhook at your store to your Stripe account dashboard, and add the webhook signing secret it generates to the Stripe SCA payment module configuration.

Login to your account at the Stripe web site, and select Developers > Webhooks
- select '+ Add endpoint' at the upper right of the page
- set the URL to: https://yourstore.url/ext/modules/payment/stripe_sca/webhook.php
- select version as 'Latest API version'
- select event 'payment_intent.succeeded' and 'payment_event.payment_failed'
- click 'add endpoint' to save the webhook endpoint.

Then select the new endpoint URL from the list of end points, and then 'click to reveal' to see the Signing Secret. Copy and paste the text of the signing secret to the Webhook Signing Secret in the Stripe SCA module configuration form.

The Stripe SCA module adds a log table, stripe_event_log, to the database, and if you select 'Log events?' in the Stripe SCA configuration, it will record each Stripe API call with the parameters that are passed to Stripe and the response received.

As the process flow has changed to use a web hook, the order has to be created in a pending state, and then updated to completed status after the payment has been authorised. Consequently, you need to set the new order status to 'Preparing [Stripe SCA]', and the order status is set to the status the order is to be set to, after the payment is authorised.

Technical Notes

The current stripe-php library, as at module publish date, has been included in in the module install. Calls to the Stripe library functions have replaced directly sending transactions to the Stripe gateway. You should be able to replace the includes/modules/payment/stripe_sca folder with the complete contents of the stripe-php library when Stripe releases updates to their library. If you do so, set the new API version in includes/modules/payment/stripe_sca.php.

The Stripe v3 process flow now requires a PaymentIntent to be created before the payment page is displayed, and a 'data secret' it generates to be included in the HTML form. If a saved card is used, the Stripe customer id and payment method id has to be added to the PaymentIntent. During coding, it was found that a payment method could not be removed from a PaymentIntent, so rather than update the PaymentIntent with a server call as the saved card/new card is selected, the adding of the customer and payment method is deferred until immediately before submitting the payment to Stripe in a Javascript call when the form is submitted. The payment_intent.php server hook is also used to save the value of the 'save card' check box in the PaymentIntent so it is accessible to the webhook called after the payment is authorised.

Stripe v3 provides UI elements to collect card details. A 'card-element' element is required for the new card to show card number, expiry and CVC fields, but is also required for saved cards in order to provide a place holder that Stripe can use to display authorisation prompts if required. Consequently, two occurrences of the 'card-element' element were created with the name of each toggled depending on whether a saved card or new card is selected. Otherwise, trying to reuse the same element for both purposes block the authorisation of saved card when the new card details was hidden.

All order fulfilment and card saving code has been moved to ext/modules/payment/stripe_sca/webhook.php.

Note the DIR_FS_CATALOG constant should be set to a path string, rather than the value  dirname($_SERVER['SCRIPT_FILENAME']) . '/' because the includes/modules/payment/stripe_sca.php has a require that references the stripe-php library, and is executed at different locations in the directory structure and fails when the DIR_FS_CATALOG value varies with location.

 

stripe_sca_v1.0.zip

Link to comment
Share on other sites

Probably best to leave it installed but turned off for the time being.

Please be aware that this module has not been proven in production. I only completed it today, and whilst I have checked it's operation with all the Stripe test cards, and all the save card functions appear to work ok, there is a risk there might be something I missed.

Link to comment
Share on other sites

I understand, I have a Phoenix 1.0.2.2 on Xampp and a Frozen live shop. I will have a play this afternoon (UK Time)

Edited by mhsuffolk

Live shop Phoenix 1.0.8.4 on PHP 7.4 Working my way up the versions.

Link to comment
Share on other sites

I believe there is a typo:

Quote

- select event 'payment_intent.succeeded' and 'payment_event.payment_failed'

should be:

Quote

- select event 'payment_intent.succeeded' and 'payment_intent.payment_failed'

"'payment_event.payment_failed" is not in the drop down list

Link to comment
Share on other sites

Thank you @asro2004,

I tested on a live shop and found the following:

- in test mode: stucks on checkout_confirmation.php => card data filled in => pressed confirmation button => button stays disabled => doesn't forward, no payment processed

- in live mode: payment got processed,but I got redirected to the empty shopping cart instead of checkout success. Payment correct registered, but order is not processed neither saved in the store db.

Some issues:

- the option "Save Card for next purchase?" shows on checkout_confirmation.php even it is disabled in the module.

-  "CVC" shows on checkout_confirmation.php even it is disabled in the module.

Link to comment
Share on other sites

Phoenix 1.0.2.2  PHP 7.3 Xampp

In includes/module/payments/stripe_sca.php I get lots of these

Warning: Use of undefined constant TABLE_ORDERS - assumed 'TABLE_ORDERS' (this will throw an Error in a future version of PHP) in D:\Phoenix_7_3\htdocs\includes\modules\payment\stripe_sca.php on line 135
1146 - Table 'phoenix.table_orders' doesn't exist

I presume it is that the file is using the old method of specifying tables from a database_tables.php. I think they all need to be hard coded e.g Line 135

tep_db_query('delete from orders where orders_id = "' . (int) $order_id . '"');

Instead of

tep_db_query('delete from ' . TABLE_ORDERS . ' where orders_id = "' . (int) $order_id . '"');

Live shop Phoenix 1.0.8.4 on PHP 7.4 Working my way up the versions.

Link to comment
Share on other sites

Many thanks for the feedback. I've made changes which I think address all issues raised so far:

  • update all SQL to use actual table name instead of string constant
  • add javascript to 'footer_scripts' template block, so loaded after jQuery in Phoenix and remove $ undefined error javascript error
  • add Bootstrap classes to form controls to improve appearance in Phoenix, and fix card element not being visible in Phoenix
  • hide 'add card' prompt in payment form when token save configuration is false
  • stop logging to event table when configuration logging setting is false
  • set module public title to 'Credit Card (Stripe SCA)' so enabling multiple credit card modules is less confusing
  • fix save card icon display in Phoenix 'my account' page
  • remove configuration option to validate CVC, as card fields are managed by Stripe

The updated module is attached. It has been tested on both an old Bootstrap osCommerce site and a current Phoenix, 1.02, site.

If you do not see the card number, expiry and CVC in the order confirmation payment form, please check the browser console for any javascript errors. jQuery must be loaded before the payment module script in the page source.

If you enter card details and the page hangs with the payment button disabled, please check the browser console for any javascript errors. If that's ok, check the latest rows in the stripe_event_log table. If there is not an entry for the action 'ajax retrieve', that suggests that the server hook https://yourstore.url/ext/modules/payment/stripe_sca/payment_intent.php is not accessible. Check the URL in your browser for any errors. It should show the response ' {"status":"fail","reason":"No intent id received"} '.

If the payment is processed, and the checkout success page is displayed, but the order is not complete, first check the Stripe dashboard to see if the payment was processed. If ok, check the webhook events in the stripe Developer page. It will show the response received for each webhook attempt, and may show PHP errors in the response. You may need to copy and paste to a notepad to view the messages more easily. Also check the latest rows in the stripe_event_log table. There should be a series of rows for the actions: 'webhook', 'webhook process payment', 'webhook processOrder', 'webhook updateOrderStatus', plus messages for 'webhook createCustomer' and 'webhook saveCard' if token saving is enabled and the 'save card' check box was ticked in the payment form. Check that the server hook https://yourstore.url/ext/modules/payment/stripe_sca/webhook.php is accessible. If you enter the URL in your browser, you should get a blank page displayed with no errors.

stripe_sca_v1.0.1.zip

Edited by asro2004
Add webhook test in browser
Link to comment
Share on other sites

Brilliant work so far. Have been testing it, two more small bugs

1.  In  ext/modules/payment/stripe_sca/webhook.php Line 199

                    EMAIL_TEXT_INVOICE_URL . ' ' . tep_href_link(FILENAME_ACCOUNT_HISTORY_INFO, 'order_id=' . $order_id, 'SSL', false) . "\n" .

file name needs hardcoding.

 

2.Module sort order appears not to work, always appears as the last item, I want it first!

 

Edited by mhsuffolk

Live shop Phoenix 1.0.8.4 on PHP 7.4 Working my way up the versions.

Link to comment
Share on other sites

I'll add those to my to do list. There's a couple of other items I should confess.

With the Stripe module, there's actually no code difference between test and live mode, other than displaying 'test' next to the module name on some pages. It does nothing to the messages sent to or received from Stripe. Wether it records the transaction as test or live data at Stripe is dependant on the public and secret key being the test or live version of the key.

I should have thought about that and either changed the configuration to accept both live and test keys and then use the test/live switch to switch between the two, or just remove the test/live switch. I just copied it from the old Stripe module without thinking about it.

Also, I'm embarassed to say that the authorize/capture isn't implemented either. All Stripe transactions are submitted as capture transactions regardless of the module configuration. I'll have to double check, but I think that applied to the old Stripe module as well. I can see there is an option when creating a payment intent to set it as an authorise transaction with an amount to capture. I'll include that in my to do list.

Link to comment
Share on other sites

8 hours ago, mhsuffolk said:

Module sort order appears not to work, always appears as the last item, I want it first

works for me, got mine first above paypal,

however, I can't get past the checkout_payment.php page, fatal error occurs:

Fatal error: Uncaught Error: Cannot access empty property in D:\xxxxx\xxxx\xxxx\includes\modules\payment\stripe_sca.php:832

what have I missed?

osC CE live - developing osC Phoenix adding modules with no core changes(awesome and easy!)

Link to comment
Share on other sites

I think it is to do with your secret key, have you put both the publishable key and secret key into the module. Are they both either live keys or test keys

Live shop Phoenix 1.0.8.4 on PHP 7.4 Working my way up the versions.

Link to comment
Share on other sites

1 minute ago, mhsuffolk said:

have you put both the publishable key and secret key into the module

yep, both are there in the module, and they are test keys

osC CE live - developing osC Phoenix adding modules with no core changes(awesome and easy!)

Link to comment
Share on other sites

I have successfully run test transactions on my live site. One thing that was not in the instructions is that you have to create a webhook in test mode on the Stripe site as well as in live mode. Perhaps that is the problem.

I presume you are running this locally, if so you need to install  this to overcome the fact that stripe cannot see your site files.

 

Edited by mhsuffolk

Live shop Phoenix 1.0.8.4 on PHP 7.4 Working my way up the versions.

Link to comment
Share on other sites

@mhsuffolk I think the issue is that I'm testing on a local server, and the webhook can't return to my localhost.  Looks like I'll have to test this on my live shop. 

I'll report back tomorrow

osC CE live - developing osC Phoenix adding modules with no core changes(awesome and easy!)

Link to comment
Share on other sites

The Stripe documents also suggest using ngrok to provide a link to your local server. It worked well for me in developing the module on an Ubuntu virtual machine running on a Windows 10 machine. On my development machine I set up a number of web sites with the /etc/hosts file pointing those domains to 127.0.0.1. I start ngrok with the command:

 ngrok http -host-header=mystore.com 80

and then at the Stripe dashboard edit the test web hook point end point to include the URL that the ngrok command displays after it starts. You end up with a stripe end point that looks like:

  http://af8833b2.ngrok.io/ext/modules/payment/stripe_sca/webhook.php

You have to create an account at the ngrok web site, but a free personal account seems to work fine. After installing ngrok you have initialise it with a code from your account at the ngrok web site dashboard.

 

Link to comment
Share on other sites

13 hours ago, mhsuffolk said:

2.Module sort order appears not to work, always appears as the last item, I want it first!

I'm sorry but this is outside the cope of the payment module itself. The sequence shown on the checkout page is simply the order in which the payment modules are listed in the MODULE_PAYMENT_INSTALLED configuration record.

It looks like admin/modules.php has to be updated to save the payment modules, whenever any module is changed, into the configuration value in the sequence of the sort order whereas at the moment it just adds any new module to the end of the list.

Alternatively, includes/classes/payment.php changed to sort the $selection_array array into sort order in the selection() function.

14 hours ago, mhsuffolk said:

                  EMAIL_TEXT_INVOICE_URL . ' ' . tep_href_link(FILENAME_ACCOUNT_HISTORY_INFO, 'order_id=' . $order_id, 'SSL', false) . "\n"

I've fixed this for a next release, but will wait to see if there is anything else that needs to be updated.

Raiwa is having an issue with the being redirected to the cart page after clicking finalise and pay, and I have not been able to reproduce this. Is anyone else having a similar problem?

Link to comment
Share on other sites

3 hours ago, asro2004 said:

Raiwa is having an issue with the being redirected to the cart page after clicking finalise and pay

No, mine goes on to the success page OK.

Live shop Phoenix 1.0.8.4 on PHP 7.4 Working my way up the versions.

Link to comment
Share on other sites

3 hours ago, asro2004 said:

It looks like admin/modules.php has to be updated to save the payment modules

I am out today and will look into this later. All my other payment modules (PayPal and Bank Transfer) behave correctly regarding their sort position including the original Stripe module, which is still installed but switched off

Edited by mhsuffolk

Live shop Phoenix 1.0.8.4 on PHP 7.4 Working my way up the versions.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...