apeisa

Payment base class + PaymentStripe + PaymentPaypal

Recommended Posts

Here is very simple abstract class that I hope would get ideas and contribution from community, so that different PW projects could use same payments methods in generic way: https://github.com/apeisa/Payment

Currently Payment modules just assume it's found from /site/modules/Payment/Payment.php, but I would love to get it autoloaded somehow (I went with PW module dependencies and transformed the base class into PW module also). 

Also I have tried to keep this as minimum as possible - hopefully I have not left anything too important out. 

I have also created one two payment modules, that use this base class:

https://github.com/apeisa/PaymentStripe/

https://github.com/apeisa/PaymentPaypal/

Please visit their repos for examples.

  • Like 20

Share this post


Link to post
Share on other sites

I like it, it's a good start I believe.

Personally, I have some pretty basic code to handle all errors in a localized manner (Stripe only). 

I've been meaning to do something similar, but for the Subscription part of the API. Is that something you'd like to do or do you think it's out of scope?

I ask that because subscriptions can be a lot harder to support.. when payment goes through it's all fine, but when cards expire, when people can't simply pay or else, it gets complicated.

  • Like 1

Share this post


Link to post
Share on other sites

I haven't given any thoughts on subscriptions. I suspect they are pretty hard to implement in general manner (and rare payment processors support subscription).

I think it would be nice addition to the Payment Stripe, but probably something we should leave out from base class.

  • Like 2

Share this post


Link to post
Share on other sites

Just made quite a bit refactoring on these modules and streamlined that it's totally same API usage no matter if you use "single product payment" like Stripe or "shopping cart, multiple products" like PayPal. Also PayPal payment verification is based on invoice id also, so you cannot spoof it with any earlier payment (earlier verification was amount only).

  • Like 3

Share this post


Link to post
Share on other sites

Antti, 

Curious why you moved away from the abstract class / non module version.

Share this post


Link to post
Share on other sites

I haven't given any thoughts on subscriptions. I suspect they are pretty hard to implement in general manner (and rare payment processors support subscription).

I think it would be nice addition to the Payment Stripe, but probably something we should leave out from base class.

Sounds good. I already need to be working on this for a few personal projects I want to implement. I'll look at your source more closely and see if I can make similar design decisions to streamline payments workflow on PW. Cheers!

  • Like 3

Share this post


Link to post
Share on other sites

Antti,

Curious why you moved away from the abstract class / non module version.

It's how autoloading is done in PW. Also that was nice play to add "active payment modules" setting.

  • Like 1

Share this post


Link to post
Share on other sites

Thanks. I have a few base class process modules. When I saw that you were using a non module version, I was curious if there was a reason.

Then I saw you moved away from it, so I had to ask.

:)

Share this post


Link to post
Share on other sites

I felt dirty having fixed path for base class. Requires definition in module info is much nicer.

  • Like 1

Share this post


Link to post
Share on other sites

Haha. Yeah…


Also, I'm super stoked on all this payment stuff. :)

  • Like 1

Share this post


Link to post
Share on other sites

On the subject of subscriptions, other projects I've seen on Github that link to Stripe etc took the understandable view that subscriptions are handled slightly differently by different payment providers with some many not offering subscriptions at all, so the view on a few projects has been that the subscription should be handled by the system using the module, and payment modules are better off handling single payments.

What I mean is, your PW project would keep track of the next time a customer should be charged and charge them an additional single payment. Et voila, you don't need to rely on the different implementations of subscriptions that the payment providers may or may not offer :)

  • Like 1

Share this post


Link to post
Share on other sites

Just a heads up.. I have a prototype working for subscriptions and it's working pretty well.

I was thinking maybe we should offer the Stripe API as a separate module dependency, with only Stripe in it. That way I we both could use the Stripe module to load the API keys and not have conflicting Stripe installations.

Share this post


Link to post
Share on other sites

Great news Pierre-Luc!

Separate module for API keys - do you think it's worth it? For most projects I think they use either or - not both (normal and subscriptions). 

Share this post


Link to post
Share on other sites

Not only for the API keys but the whole Stripe PHP API. I do think there may be value in decoupling the API from the modules themselves. Any other module (or project) requiring the API wouldn't have to maintain it themselves, which could otherwise lead to problems when loading it twice, or having conflicting versions. 

Implementing subscriptions is going to be a lot of work, not only do I need to implement subscriptions, I need to add plans (and sync them with Stripe's platform), customer management, payments (and failures), web hooks and a bunch of other stuff like coupons. Right now I'm aiming at making it work within the module itself, but I'm starting to wonder if there wouldn't be value in simply doing a whole Stripe package instead. I really don't have an answer as of yet.

I think it's pretty cool to have an agnostic "framework" like you are implementing with support for various payment processors. I wonder though how far this is possible considering the differences in both APIs. I only have much experience with advanced Stripe, so take this as a grain of salt. What's your end goal with this? How far are you thinking of taking it, or do you simply want to have an easy way to make simple payments?

Share this post


Link to post
Share on other sites

Not only for the API keys but the whole Stripe PHP API. I do think there may be value in decoupling the API from the modules themselves. Any other module (or project) requiring the API wouldn't have to maintain it themselves, which could otherwise lead to problems when loading it twice, or having conflicting versions. 

Yeah, I know what you mean. What I meant that separating Stripe API would really be beneficial if you actually need Stripe in multiple modules in single site. Of course it would be pretty trivial to bundle API (and having api keys as settings) as separate module, so I don't see much harm in that either.

I think it's pretty cool to have an agnostic "framework" like you are implementing with support for various payment processors. I wonder though how far this is possible considering the differences in both APIs. I only have much experience with advanced Stripe, so take this as a grain of salt. What's your end goal with this? How far are you thinking of taking it, or do you simply want to have an easy way to make simple payments?

Regarding Payment Module (the base module) - I think feature set is pretty much there: supporting single time payments with multiple items/products/rows and customer information. If we go further than that, base class will be covering more stuff than many payment gateways offer, so you cannot really use it in generic way.

For subscriptions, I am not sure if it is good idea to try abstracting them. My reasoning is that need for subscriptions are pretty specific (pretty much webapps, donations and payment walls) and all the gateways offer very different solutions. So it will be big task that will benefit only projects where pretty much will be custom customer handling logic anyways.

So if you go further with Stripe subscriptions and decide to keep Stripe API as separate module, I am of course interesting using it instead of bundling stripe php sdk with PaymentStripe. I am not planning to add subscription support into PaymentModule. But if you think it would be simple task (it seems it's not?) to add somekind subscription support directly into PaymentStripe, then I'm fine with that route too!

Share this post


Link to post
Share on other sites

Sounds good!

I am definitely going forward with the subscription module, so I am indeed interested in having the API as a separate module.

I would make it a pretty simple configurable module:

public function init() {
        require_once(__DIR__."/stripe/lib/Stripe.php");
        Stripe::setApiKey($this->stripeApiKey);
}

public static function getModuleConfigInputfields(array $data) {
$inputfields = new InputfieldWrapper(); 

// Option to set the Stripe API Key
$fieldApiKey = wire('modules')->get('InputfieldText');
$fieldApiKey->name = 'stripeApiKey';
$fieldApiKey->label = __("API Key");
$fieldApiKey->description = __("Set your live or test secret Stripe key.");
if(isset($data['stripeApiKey'])) $fieldApiKey->value = $data['stripeApiKey'];
$inputfields->add($fieldApiKey);

return $inputfields; 
}

And possibly a default currency as $this->defaultCurrency.

  • Like 1

Share this post


Link to post
Share on other sites

Hi guys,

I am a bit confused with the different PayPal payment modules existing. There's this new PaymentModule and there's the old Paypal payment method for ProcessWire Shop module. I used the ShoppingCart module with my current ProcessWire site and would like to add a PayPal payment method. So I installed the new PaymentModule, PaymentInvoice and PaymentPaypal. On the checkout page, I get this:

<label for='paymentmethod'>Payment method: <span class='reqstar'>*</span></label><select name='paymentmethod'><option  value='PaymentModule'></option><option  value='PaymentInvoice'>Invoice</option><option  value='PaymentPaypal'></option></select>

So in the dropdown, the first (PaymentModule) and third line (PaymentPaypal) are empty and only the Invoice is written down though all three are selectable.

I chose Paypal - nothing happened, the whole output was: "1".

Well... I deinstalled the Paypal module and tried to install the old Paypal payment method. On install, the first error message informs me there's no PaymentAbstract.php to include. Copied the file from site/modules/ShoppingCart to site/modules/PaymentPaypal and tried again. Result:

"Compile Error: Cannot redeclare class PaymentAbstract (line 3 of /var/www/processwire/site/modules/PaymentPaypal/PaymentAbstract.php)"

Any ideas what I did wrong? Is it right that I should use the deprecated PayPal method with the ShoppingCart module?

Thanks

sarah

Share this post


Link to post
Share on other sites

Yep, the deprecated paypal module is for the shop-for-pw.

  • Like 1

Share this post


Link to post
Share on other sites

Yep, the deprecated paypal module is for the shop-for-pw.

Hi apeisa,

thanks for your reply! So what will I do to install the deprecated paypal module without getting the error message? Only install shop-for-pw (ShoppingCart and ShoppingCheckout) and the old paypal module? Right now I also have the PaymentModule installed as well.

Sarah

Edited by sarah_hue

Share this post


Link to post
Share on other sites

No need for paymentmodule either. These are new more general payment modules, that don't have anything to do with the old shop module of mine. I tried hard to get different naming, but didn't get any ideas.

  • Like 1

Share this post


Link to post
Share on other sites

No need for paymentmodule either. These are new more general payment modules, that don't have anything to do with the old shop module of mine. I tried hard to get different naming, but didn't get any ideas.

Alright, now I get it.

Though I can't manage to get the module running: I uninstalled everything except for shop-for-pw (ShoppingCart and ShoppingCheckout). When I try to install the old paypal method zip file, the admin page returns this error:

Compile Error: require_once(): Failed opening required '/var/www/processwire/site/modules/PaymentPaypal/PaymentAbstract.php' (include_path='.:/usr/share/php:/usr/share/pear') (line 3 of /var/www/processwire/site/modules/PaymentPaypal/PaymentPaypal.module)

So again I copied PaymentAbstract.php into /PaymentPaypal/, and again the error message changes to:

Compile Error: Cannot redeclare class PaymentAbstract (line 3 of processwire/site/modules/ShoppingCart/PaymentAbstract.php)

Share this post


Link to post
Share on other sites

Okay, got it: While the PaymentAbstract.php is in /ShoppingCart/, PaymentPaypal.module installs into a new folder /PaymentPaypal/ and cannot be installed when in /ShoppingCart/. So I just edited this line of /site/modules/PaymentPaypal/PaymentPaypal.module

require_once(dirname(__FILE__) . '/PaymentAbstract.php');

into this:

require_once(dirname(__FILE__) . '/../ShoppingCart/PaymentAbstract.php');

Now it's possible to install the paypal method and use it with ShoppingCheckout.

Share this post


Link to post
Share on other sites

Thanks for these modules. When I try using the Stripe module, I get the following error:

Fatal error: Exception: Method PaymentStripe::embed does not exist or is not callable in this context

I can see at the end of the module code the default for the switch is calling this. It appears as though it's here that determines the "step" and should reload with the appropriate get variable in the URL. I'm not sure how to go about making this work. Any help would be appreciated.

Thanks.

Scratch all that. I was forgetting to call the charge url with ?step=process. Rookie mistake. Works great!

  • Like 1

Share this post


Link to post
Share on other sites

I just started my first website with Padloper and paypal payment module and I have some issues with the Paypal module, I'm on it since yesterday and I'm totally lost...

Everything is fine, I confirm the payment, paypal say that the payment has been completed, but when I'm redirected on Padloper , I'm redirected to the failure page but whithout any failure message. If I check my test paypal account the payment has been completed, so no errors.

More strange, if I test my website in local, everything is fine !  
but online, in the processPayment function of the paypal module, the request return ... false.
And only "false". 
 

$http = new WireHttp();
$response = $http->post($this->endpoint . 'cgi-bin/webscr', $postParams); 
var_dump($response);

Why no error code or some indications ? the payment has been made, and in local I have a response, with SUCCESS.

I'm using OVH, do I need to buy a SSL certificate for communicating with paypal ? 

If someone can help me, I will be forever grateful !   :D

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.