mollie / mollie-api-php

Mollie API client for PHP
http://www.mollie.com
BSD 2-Clause "Simplified" License
551 stars 189 forks source link

Uncaught Error: Call to a member function createPayment() on string <yada yada>examples/customers/create-customer-first-payment.php #491

Closed Antoine-TheDutch closed 4 years ago

Antoine-TheDutch commented 4 years ago

Specifications

Describe the issue

I'm trying to understand the whole process of setting up a subscription payment: When I get to this script: I get errors in the examples, and after banging my head for a week now, I'm completely lost.

1) I want to understand the order in which the process flows (and what scripts are called) 2) Why am I getting this error? I am so stuck :( ...

sandervanhooft commented 4 years ago

Please be careful with your head, you only have 1 (I assume) 😉 .

A good resource to learn about Mollie's subscription payments can be found here.

Essentially, you need to

  1. Create a customer
  2. Make sure the customer has a valid mandate (use a so called "first payment" to generate one)
  3. Then create the subscription for this customer.

If you keep getting stuck, let me know at what step specifically so I can take you from there.

Antoine-TheDutch commented 4 years ago

I knew I just needed a dutch hug. :) Thx Sander for the pointer. Let me read the content and see if I understand Or maybe we setup a quick call..

MollieRick commented 4 years ago

Hi @Antoine-TheDutch,

Still corona, so we will send you some virtual hugs! :D You can always reach us as well via info@mollie.com.

Antoine-TheDutch commented 4 years ago

My understanding so far:

1) generate a client for the website (store it in mariadb) 2) Call this script: create-customer.php 3) return is a cst_42649246298 customer ID -> add to dbase line of customer 4) call create-customer-first-payment.php -> Uncaught Error: Call to a member function createPayment() ..

Thats where the trouble starts

sandervanhooft commented 4 years ago

The examples are not intended to execute or use in production, more as reading material.

$customer = $mollie->customers->create([
    // customer details here
]);

// First payment to get the customer's mandate
$firstPayment = $mollie->payments->create([
    'sequenceType' => 'first',
    'webhookUrl' => 'https://your-webhook-url',
    'redirectUrl' => 'https://your-redirect-url',
    'amount' => [
        'value' => '0.25',
        'currency' => 'EUR',
    ],
    'description' => 'Authorization payment',
    // More payment details...
]);

// Redirect the customer to Mollie's checkout

Then in your webhook handler (notice this is a completely separate call/script):


$id = $request->get('id');
$payment = $mollie->payments->get($id);

if($payment->status === 'paid')
{
    // The customer has paid the first payment, you can now start the subscription
   $customer = $mollie->customers->get($payment->customerId);
   $customer->createSubscription([
      "amount" => [
            "currency" => "EUR",
            "value" => "25.00",
      ],
      "times" => 4,
      "interval" => "3 months",
      "description" => "Quarterly payment",
      "webhookUrl" => "https://webshop.example.org/subscriptions/webhook/",
   ]);
}
Antoine-TheDutch commented 4 years ago

I Am aware about the examples, I' basically kicking them off to understand the flow.

I found why it was crashing; I changed the following;

What is the differentence in create-first payment between:

/ me pushing a client_id / $customer = "cst_fBQEbrGcrQ"; # the reason why it crashed!!

/ the script original / $customer = $mollie->customers->page(null, 1)[0];

Reason I want that is: how I'm going to make absolutly shure, without a doubt, that the payment goes to the right customer_ID?

Should I combine the 2 scripts into 1, so It is within the same runtime? or am I crashing a prosedure them.. I mean doing something like:

So I now combined this: $customer = $mollie->customers->create(["name" => "Tinus Plotseling", "email" => "tinus@example.org", "metadata" => ["isJedi" => \TRUE]]);

$customer = $mollie->customers->page(null, 1)[0];

So in my script it will end up line:

But what I am now wondering:

/*AA: I added next line from create customer */
$customer = $mollie->customers->create(["name" => "Tinus Plotseling", "email" => "tinus@example.org", "metadata" => ["isJedi" => \TRUE]]);

/* insert mollieId into customerdb */
$conn->query("UPDATE customers SET mollieId='$customer->id' where customer_id='$cid'";      

/*why does it have to take it from mollie and not from my db?? */   

$customer = $mollie->customers->page(null, 1)[0];
Antoine-TheDutch commented 4 years ago

Another food for thought for me is: can I push multiple subscriptions to the same client?.

I have that situation, so what do you suggest?

sandervanhooft commented 4 years ago

Sure, one customer can have multiple subscriptions.

sandervanhooft commented 4 years ago

/why does it have to take it from mollie and not from my db?? /

Not sure what you mean, but you can also fetch the customer using the customer id:

$mollie->customers->get($customerId);
Antoine-TheDutch commented 4 years ago

I used that now indeed.

I'm almost there.

Customer setup DONE Mandate payment DONE Subscription DONE (although I think I missed the part where it provides the subscription ID)

Now i want to understand the subscription

I'm trying to find info on the subscription webhook. What does it call for? What dies it provide? Do you have any details on that (i know this is the wrong platform to ask :)

I will grant back a subscription what I did to the community, for other idiots like me.. :)

AA

sandervanhooft commented 4 years ago

https://docs.mollie.com/payments/recurring#payments-recurring-subscription-webhooks

The webhook request will only provide a paymentId and will be called in these cases.

Antoine-TheDutch commented 4 years ago

I apologize sander if I just dont understand the documents.: (maybe i'm getting too old :) )

Can you give me a code example on the subscription webhook?

What is it that exactly happens?

What I understand is: the moment the subscription is made it immediately calls the webhook.. (so I made another webhook script specifically for this webhook call. ) The only webhook example on github shows how to pull a payment

What I got from a forum is:

The webhook calls with an id (hopefully a payment id) How do I get the subscription ID from the API,

I can't find it anywhere in any of the examples.

A

Antoine-TheDutch commented 4 years ago

Do I understand it correctly that the sun_webhook.php is actually is a "form post" to that script.. (just to make it logical) ? (if that is the case, I completely missed it) I just see it on my access log:

[09/Sep/2020:14:15:22 +0200] "POST /sub_webhook.php HTTP/1.1" 404 16 "-" "Mollie HTTP client/1.0"

So in that case it should be:

$resource = $_REQUEST["resource"]; / this gives me what the id value is / $id = $_REQUEST["id"];

etc etc.. based on this piece of docu:

HTTP/1.1 201 Created Content-Type: application/hal+json
{ "resource": "subscription",
"id": "sub_rVKGtNd6s3",
"mode": "live", "createdAt": "2018-06-01T12:23:34+00:00",
"status": "active",
"amount": {
"value": "25.00",
"currency": "EUR" }, -- | --

sandervanhooft commented 4 years ago

The webhook you set on the subscription is actually used for the subscription payments.


$subscription = $customer->createSubscription([
    'webhookUrl' => 'https://webhook-to-be-called-when-payments-are-updated`
    // rest of subscription payload here
]);

// You now have the subscription id
$subscription->id;
sandervanhooft commented 4 years ago

It's indeed a POST request.

$resource = $_REQUEST["resource"]; // no, the resource will not be sent
$id = $_REQUEST["id"]; // yes, the id will be there
Antoine-TheDutch commented 4 years ago

Is this then a correct sequece:

$id = $_REQUEST["id"]; $payment = $mollie->payments->get($id); $customer = $mollie->customers->get($payment->customerId); $subscriptionId = $$mollie->customers->get($payment->subscriptionId);

sandervanhooft commented 4 years ago

Yes that should work

Antoine-TheDutch commented 4 years ago

Figured it out: (finally):

The subscription webhook script php should should at least look like this

<?php
$id = $_REQUEST["id"];                                             // start by getting ID
try {
   require "initialize.php";                                           // Initialize mollie API
   $payment = $mollie->payments->get($id);        // Fill $payment with info from the ID we got
   $subscription_id = $payment->subscriptionId;   //  Extract the subscriptionId
  $customer_id = $payment->customerId;              // Extract the customerId

   if ($payment->isPaid())  {
   // do stuff when things are paid
   } elseif ($payment->isExpired()) {
    /* Here you write actions that need to happen when it is expired */
   } elseif ($payment->isFailed()) {
    /* Here you write actions that need to happen when it is failed */
   } elseif ($payment->isCanceled()) {
    /* Here you write actions that need to happen when it is canceled */
   }
} catch (\Mollie\Api\Exceptions\ApiException $e) {
    echo "API call failed: " . \htmlspecialchars($e->getMessage());
}
?>

I'll write a complete guide as my contribution to the community.