New Member
Posts: 44
Registered: ‎10-07-2015
Kudos: 36

Stripe Refunds Webhook Not Working

[ Edited ]

Stripe Credit Card Refunds are not working either.

 

I refunded a $1 stripe test cc payment from the dashboard that had already cleared.  Webhook failed on the refund with the following API JSON:

 

POST /v1/charges/ch_1EKDOWENEEDTOSECURETHESE/refund

2019/04/03 02:01:27
 
Summary
ID
req_RWrpKiTF4qih6t
Time
2019/04/03 02:01:27
Method
POST
URL
/v1/charges/ch_1EKDOWENEEDTOSECURETHESE/refund
Status
401
IP address
69.193.127.122 (from server at 52.43.191.238)
Source
Dashboard — drphipps@live.com
Related
charge — ch_1EKDOWENEEDTOSECURETHESE
Origin
 
Response body
 
{
 
"error": {
 
"code": "additional_privileges_required",
 
"message": "This action requires additional privileges.",
 
"message_code": "additional_privileges_required",
 
"type": "invalid_request_error"
 
}
 
}
New Member
Posts: 44
Registered: ‎10-07-2015
Kudos: 36

Stripe ACH Verification Deposit Amounts

UI Bug, it will not accept these amounts with a preceeding "." like .24 and .26 deposit amounts have to be entered as "24" and "26" without the decimal or they are rejected as invalid.

Ubiquiti Employee
Posts: 1,476
Registered: ‎03-21-2016
Kudos: 244
Solutions: 161

Re: Stripe Refunds Webhook Not Working

Hello @drphipps,

 

I'll try to answer all your questions from all the topics:

1) UCRM returns 200 OK for all webhooks, that are correctly processed. If there is no text in the response, it means the webhook was processed correctly. The only text that can appear for 200 OK is info that the webhook was ignored by UCRM, because it's not handled at all, so we don't want Stripe to resend it. You can read more here https://community.ubnt.com/t5/UCRM/uCRM-2-14-7-Not-Recording-First-Subscription-Payment/m-p/2733012#...

 

2) None of the breaking changes in Stripe API (from 2019-03-14 and 2019-02-19) concern UCRM as all of these changes are not related to any API, that UCRM uses.

 

3) The changes introduced in UCRM 2.15.x are related to:

  1. extended logging - when payment is not imported to UCRM the response text contains reason why + webhook events not processed by UCRM are logged as well
  2. fallback matching of payments based on subscription ID, there was a problem with payments not matched via customer ID, which we still can't reproduce, but this fallback seems to fix the problem for the user, that reported it

4) To find out if there were any API errors related to Stripe, you can check the "Developers" dashboard in your Stripe account. There is a monitoring section there. If there are no errors there, you can also check the "Logs" section under the Developers menu. If you see any errors, please post information about them here.

The only errors, that are OK in API calls are 404 Not Found errors for payment plans and customers, UCRM makes API calls to check if they already exist - 404 response means they don't and UCRM code handles that accordingly.

 

5) Stripe refunds are not implemented at all in UCRM, there is a feature request related to this, please kudo it to help us prioritize https://community.ubnt.com/t5/UCRM-Feature-Requests/Better-Integration-with-Stripe/idi-p/2285384 - for now you have to handle refunds manually.

 

Highlighted
New Member
Posts: 44
Registered: ‎10-07-2015
Kudos: 36

Re: Stripe Refunds Webhook Not Working

Its still not matching the transaction on subscriptions that were created before the 2-15-1 upgrade. 

 

One time payments on stripe ACH immediately show a Pending payment, Stripe ACH linked subscriptions do not show pending after the transaction, allowing customer to make multiple subscriptions on the same invoice. 

 

Once again, what Stripe API version is UCRM expecting?

 

The reason you could not replicate this problem is because your Stripe account is probably responding in the API version youre expecting.  Please note the Stripe API version from the screenshot.

 

Also, please update the code on ucrm to parse the JSON Header that specifies API version the JSON is encoded in.  

 

Also, need to unify the code used for subscriptions vs 1 time payments for stripe on both cc and ach, youre making requests using 2 different stripe api versions nomenclature.  

 

Lastly we need a way to put in transaction data for failed webhooks.  Perhaps poling stripe every 6 hours to pick up any that got missed.  This is supported and documented by stripe.

New Member
Posts: 44
Registered: ‎10-07-2015
Kudos: 36

Re: Stripe Refunds Webhook Not Working

Bug:

 

Mass portal invite emails crashes UCRM when it encounters ClientID with null value for email address.

 

Clients with userID higher than the one without email address do not get portal invite.

Ubiquiti Employee
Posts: 1,476
Registered: ‎03-21-2016
Kudos: 244
Solutions: 161

Re: Stripe Refunds Webhook Not Working

@drphipps

 

1) UCRM 2.15.1 is tested against Stripe API versions 2018-07-27 and 2019-03-14, it's correctly working for both (one-time payments, subscriptions, linked subscriptions, both CC and ACH)

 

2) Subscriptions and one-time payments use different API methods (not versions!), because one-time payments do not require webhooks and subscriptions do. We don't want to change this, because if you only want to use one-time payments, you don't have to configure webhooks.

 

3) When webhooks fail for any reasons (i.e. UCRM does not respond with 200 OK), Stripe will resend the webhooks later.

From Stripe docs:

In live mode, Stripe attempts to deliver your webhooks for up to three days with an exponential back off. In test mode, Stripe retries three times over a few hours.

So there should be no need to poll Stripe for missed webhooks, you would have to have UCRM offline for at least 3 days to miss a Stripe webhook.

 

If you need to resend some webhook events manually, you can do that from your Stripe dashboard in the event's detail page by using the "Retry all webhooks" button:

Screenshot 2019-04-04 at 13.13.11.png

 

4) Stripe ACH linked subscriptions do not create pending payment, but they do create the subscription item right away, so customer can see they have the subscription created.

Screenshot 2019-04-04 at 13.15.51.png

 

5) As for the unmatched transactions created before 2.15.1, can you please try to find the events regarding this in Stripe dashboard -> Developers -> Events and resend them? They will be called something like "cus_ABCDefgh123456 was charge $12.34 USD" and when you open them the event type will be "charge.succeeded"

Ubiquiti Employee
Posts: 1,476
Registered: ‎03-21-2016
Kudos: 244
Solutions: 161

Re: Stripe Refunds Webhook Not Working

[ Edited ]

duplicate

New Member
Posts: 44
Registered: ‎10-07-2015
Kudos: 36

Re: Stripe Refunds Webhook Not Working

[ Edited ]

@UBNT-Ondra I have found the charge.succeeded and UBNT endpoint received it and discarded it when it didn't match anything.  So the issue isn't that it wasn't received by UCRM the issue is that UCRM discarded the transaction.

UCRM-Ignoring.jpg

 

200 "OK" 

Response

Payment with Stripe Charge ID "ch_1EKs4RFwR9qqYiK3S7nMUBvU" does not belong to UCRM, ignoring.

(Seriously, someone had to write this error message and commit it to your CVS along with this code, when do we EVER IGNORE A PAYMENT EVENT, PAYMENT EVENT MEANS MONEY IS RECEIVED, PAYMENT EVENT IS LIKE CASH YOU DON'T DISCARD CASH SO WHY WOULD WE DISCARD A PAYMENT EVENT?)

If you're ignoring then this should have been:

404 "NOT FOUND"

Response

No such event: "ch_1EKs4RFwR9qqYiK3S7nMUBvU" 

UCRM-404NotFound-inline.jpg

 

Under NO CIRCUMSTACES should UCRM be discarding a charge.succeeded ... if there's an ERROR and the 'charge.succeeded' doesn't match anything it needs to be attached to something in UCRM to be able to be manually associated with the proper invoice.

 

If Stripe suddenly starts sending 'charge.succeeded' for transactions UCRM doesn't recognize because of a software upgrade to UCRM, for instance, you CANNOT "200 OK" the charge.succeeded AND discard the Data. 

 

If it doesn't match a transaction it either needs to be rejected with "404 Not Found" so that the transaction isn't finalized on Stripe side or you have to STORE THE DATA FOR MANUAL INTERVENTION.

 

I have a plethora of duplicate transactions initiated by customers paying their bills multiple times because it's still showing due after they paid it with Stripe.

 

We have been several days now unwinding this mess and I cannot imagine we are the only victims of this.

 

I am going to go re-run the webhooks per your instructions. 

 

We had already done this once and UCRM still wasn't accepting the webhooks.

 

----

 

 

New Member
Posts: 44
Registered: ‎10-07-2015
Kudos: 36

Re: Stripe Refunds Webhook Not Working

[ Edited ]

And for the record yes we have 258 charge.succeeded transactions half or more of them are DUPLICATE PAYMENTS ON THE SAME SUBSCRIPTION

 

SO ISSUE NUMERO UNO IS DISABLING THE PAY NOW ON AN INVOICE AFTER A SUBSCRIPTION IS CREATED, NOT RELY ON THE RESULTING ENDPOINT ACH PAYMENT THAT MAY OR MAY NOT POST PROPERLY IN 5-7 DAYS.  THIS NEEDS TO CHANGE TO "PENDING" IMMEDIATELY THE SAME WAY IT DOES WITH A ONE TIME ACH PAYMENT.  NOT STILL BE FLASHING UP THERE WITH A BIG GREEN BUTTON SAYING "PAY NOW" TO BE HIT MULTIPLE TIMES.

 

WHAT IS UNCLEAR HERE?  WE NEED A METHOD OF RECONCILATION OF THE DATA, ALL OF THE DATA, THAT IS ACCEPTED WITH A 

 

200 OK

 

YOU CAN'T DISCARD ANYTHING WITH A 200 OK, YOU'VE GOT TO DO SOMETHING WITH IT

 

SURELY THESE CHARGE.SUCCEEDED EVENTS ARE IN UCRM SOMEWHERE JUST NOT ASSOCIATED

 

Logically I should see these transactions in UCRM here:

unattached-payment-inline.jpg

I unattached a manual correction we had made one a customer to demonstrate!

 

WHERE, WHEN, HOW DO WE FIX THIS, EVEN BY HAND THIS IS STILL GOING TO BE BROKEN WHEN MONTH 2 ROLLS AROUND ON THESE SUBSCRIPTIONS.

 

AND WHAT IS THIS TRIAL MODE THING YOU'RE DOING WITH STRIPE?

 

NOT DOCUMENTED ANYWHERE

UCRM-Stripe-TrialEnds-inline.jpg

 

AND I DARE SAY WE NEED A WAY TO ISSUE THESE 100+ REFUNDS OF DUPLICATE PAYMENTS

 

New Member
Posts: 44
Registered: ‎10-07-2015
Kudos: 36

Re: Stripe Refunds Webhook Not Working

I have the JSON for each transaction how do we expose the subscription's metadata to know what to use with the POST methods to manally fix this.

 

Or if you could provide a generic POST method suitable for marking the subscription's first payment paid.

 

For the record NEW subscriptions started after the 2.15.1 upgrade are working but customers are still able to pay the invoice again after starting a subscription with Stripe ACH which is a huge issue for us.

New Member
Posts: 44
Registered: ‎10-07-2015
Kudos: 36

Re: Stripe Refunds Webhook Not Working

[ Edited ]

By the way, did I mention you can {{POLL STRIPE}} AND IT WILL GLADLY UPDATE YOU ON ANY SUBSCRIPTION'S PAYMENT STATUS!!!

 

{
 
"error": {
 
"code": "resource_missing",
 
"message": "No such event: ch_1EKs4RFwR9qqYiK3S7nMUBvU",
 
"param": "id",
 
"type": "invalid_request_error"
 
}
 
}
{
 
"error": {
 
"code": "resource_missing",
 
"message": "No such plan: ucrm_stripe_p53_1554389638",
 
"param": "plan",
 
"type": "invalid_request_error"
 
}
 
}
New Member
Posts: 44
Registered: ‎10-07-2015
Kudos: 36

Re: Stripe Refunds Webhook Not Working

Ideally you would just give us a "Subscriptions" on the left hand pannel where we can see the subscriptions active and see/edit the metadata when necessary.

 

We cannot even manually add these payments because you're not exposing the fields to us:

 

add-payment-expose-stripe-fields.jpg

 

We can see them, but not edit, in "Payments"

 

But I cannot find anyway to see the "Subscriptions" that don't yet have attached payments.

 

This seems to be an oversight.

.

New Member
Posts: 44
Registered: ‎10-07-2015
Kudos: 36

Re: Stripe Refunds Webhook Not Working

[ Edited ]

@UBNT-Ondra 

 

$This.This entry in prod.log seems to be the root of the issue:

 

[2019-04-02 11:41:40] request.INFO: Matched route "stripe_success". {"route":"stripe_success","route_parameters":{"_controller":"AppBundle\\Controller\\ClientZone\\OnlinePaymentController::stripeSuccessAction","token":"93fbobfuscated1eb655726191ec165cb","_route":"stripe_success"},"request_uri":"https://obfuscated.net/online-payment/stripe-success/93fb8f058729a1eb655726191ec165cb","method":"POS..."} []
[2019-04-02 11:41:40] security.DEBUG: Read existing security token from the session. {"key":"_security_main","token_class":"Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken"} []
[2019-04-02 11:41:40] security.DEBUG: User was reloaded from a user provider. {"provider":"Symfony\\Bridge\\Doctrine\\Security\\User\\EntityUserProvider","username":"obfuscated@ymail.com"} []

[2019-04-02 11:41:43] app.CRITICAL: Uncaught PHP Exception Symfony\Component\Debug\Exception\ContextErrorException: "Notice: Undefined index: Request-Id" at /usr/src/ucrm/src/AppBundle/Component/Stripe/Charge.php line 84 {"exception":"[object] (Symfony\\Component\\Debug\\Exception\\ContextErrorException(code: 0): Notice: Undefined index: Request-Id at /usr/src/ucrm/src/AppBundle/Component/Stripe/Charge.php:84)"} []
[2019-04-02 11:41:45] security.DEBUG: Stored the security token in the session. {"key":"_security_main"} []
[2019-04-02 13:54:17] request.INFO: Matched route "stripe_success". {"route":"stripe_success","route_parameters":{"_controller":"AppBundle\\Controller\\ClientZone\\OnlinePaymentController::stripeSuccessAction","token":"9b4feobfuscated93cd76985c373a6287","_route":"stripe_success"},"request_uri":"https://obfuscated.net/online-payment/stripe-success/9b4fe3554obfuscated985c373a6287","method":"POST"} []
[2019-04-02 13:54:17] security.DEBUG: Read existing security token from the session. {"key":"_security_main","token_class":"Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken"} []
[2019-04-02 13:54:17] security.DEBUG: User was reloaded from a user provider. {"provider":"Symfony\\Bridge\\Doctrine\\Security\\User\\EntityUserProvider","username":"robfuscated@lti.cc"} []

[2019-04-02 13:54:19] app.CRITICAL: Uncaught PHP Exception Symfony\Component\Debug\Exception\ContextErrorException: "Notice: Undefined index: Request-Id" at /usr/src/ucrm/src/AppBundle/Component/Stripe/Charge.php line 84 {"exception":"[object] (Symfony\\Component\\Debug\\Exception\\ContextErrorException(code: 0): Notice: Undefined index: Request-Id at /usr/src/ucrm/src/AppBundle/Component/Stripe/Charge.php:84)"} []
[2019-04-02 13:54:20] security.DEBUG: Stored the security token in the session. {"key":"_security_main"} []

 

Ubiquiti Employee
Posts: 36
Registered: ‎07-21-2016
Kudos: 4
Solutions: 2

Re: Stripe Refunds Webhook Not Working


> Bug:
> Mass portal invite emails crashes UCRM when it encounters ClientID with null value for email address.
> Clients with userID higher than the one without email address do not get portal invite.

Which version are you on? This seems to have been fixed in 2.15.0.
New Member
Posts: 44
Registered: ‎10-07-2015
Kudos: 36

Re: Stripe Refunds Webhook Not Working

2.15.1

Ubiquiti Employee
Posts: 36
Registered: ‎07-21-2016
Kudos: 4
Solutions: 2

Re: Stripe Refunds Webhook Not Working

Unfortunately I was unable to reproduce the problem. When I click the "Send invitations" button all users without an email are correctly skipped and the rest is processed normally.
Ubiquiti Employee
Posts: 1,476
Registered: ‎03-21-2016
Kudos: 244
Solutions: 161

Re: Stripe Refunds Webhook Not Working

Hello @drphipps,

 

  1. The error you posted from prod.log regarding "Request-Id" was already fixed in UCRM 2.15.0.
  2. The "trial ends" info appears for subscriptions, where "start date" of subscription was selected in the future. E.g. If I create subscription today with start date of April 15, it will show, that trial ends in 7 days and the first payment will be triggered then.
  3. The ignored "charge.succeeded" events when payment does not match to UCRM is feature to prevent import of payments not belonging to UCRM. This was introduced for ISPs using Stripe for more products, than just UCRM.
    We will introduce new configuration in UCRM for this, so that you can choose whether you want to ignore such payments or import them as unmatched.
  4. Regarding the duplicate payments. They are not duplicate, your clients did pay the amount, so UCRM imported the payments. That said, we understand this is a problem with UI/UX and will improve this.
    There is already slight improvement with better tooltip in subscription creation modal informing clients of current outstanding balance in 2.16 beta and we're planning more improvements for this.

 

New Member
Posts: 44
Registered: ‎10-07-2015
Kudos: 36

Re: Stripe Refunds Webhook Not Working


@UBNT-Ondra wrote:

Hello @drphipps,

 

  1. The error you posted from prod.log regarding "Request-Id" was already fixed in UCRM 2.15.0.

Just so we are clear 

 

This error was from BEFORE the upgrade to 2.15.1:

 

[2019-04-02 11:41:40] request.INFO: Matched route "stripe_success". {"route":"stripe_success","route_parameters":{"_controller":"AppBundle\\Controller\\ClientZone\\OnlinePaymentController::stripeSuccessAction","token":"93fbobfuscated1eb655726191ec165cb","_route":"stripe_success"},"request_uri":"https://obfuscated.net/online-payment/stripe-success/93fb8f058729a1eb655726191ec165cb","method":"POS..."} []
[2019-04-02 11:41:40] security.DEBUG: Read existing security token from the session. {"key":"_security_main","token_class":"Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken"} []
[2019-04-02 11:41:40] security.DEBUG: User was reloaded from a user provider. {"provider":"Symfony\\Bridge\\Doctrine\\Security\\User\\EntityUserProvider","username":"obfuscated@ymail.com"} []

[2019-04-02 11:41:43] app.CRITICAL: Uncaught PHP Exception Symfony\Component\Debug\Exception\ContextErrorException: "Notice: Undefined index: Request-Id" at /usr/src/ucrm/src/AppBundle/Component/Stripe/Charge.php line 84 {"exception":"[object] (Symfony\\Component\\Debug\\Exception\\ContextErrorException(code: 0): Notice: Undefined index: Request-Id at /usr/src/ucrm/src/AppBundle/Component/Stripe/Charge.php:84)"} []
[2019-04-02 11:41:45] security.DEBUG: Stored the security token in the session. {"key":"_security_main"} []

 

This Error was from AFTER the upgrade to 2.15.1 (When a payment cleared and that payment was initiated BEFORE the upgrade):

 

[2019-04-02 13:54:17] request.INFO: Matched route "stripe_success". {"route":"stripe_success","route_parameters":{"_controller":"AppBundle\\Controller\\ClientZone\\OnlinePaymentController::stripeSuccessAction","token":"9b4feobfuscated93cd76985c373a6287","_route":"stripe_success"},"request_uri":"https://obfuscated.net/online-payment/stripe-success/9b4fe3554obfuscated985c373a6287","method":"POST"} []
[2019-04-02 13:54:17] security.DEBUG: Read existing security token from the session. {"key":"_security_main","token_class":"Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken"} []
[2019-04-02 13:54:17] security.DEBUG: User was reloaded from a user provider. {"provider":"Symfony\\Bridge\\Doctrine\\Security\\User\\EntityUserProvider","username":"robfuscated@lti.cc"} []

[2019-04-02 13:54:19] app.CRITICAL: Uncaught PHP Exception Symfony\Component\Debug\Exception\ContextErrorException: "Notice: Undefined index: Request-Id" at /usr/src/ucrm/src/AppBundle/Component/Stripe/Charge.php line 84 {"exception":"[object] (Symfony\\Component\\Debug\\Exception\\ContextErrorException(code: 0): Notice: Undefined index: Request-Id at /usr/src/ucrm/src/AppBundle/Component/Stripe/Charge.php:84)"} []
[2019-04-02 13:54:20] security.DEBUG: Stored the security token in the session. {"key":"_security_main"} []

 

So if this was fixed in 2.15.0 then there is a REGRESSION in 2.15.1

 

Or it's just a usage case that wasn't considered, but it has us in quite a pickle.  

 

Over 100 ACH Payments were initiated by UCRM BEFORE THE UPGRADE

 

The PAYMENTS WEREN'T MATCHING ON THE ch_129zxcve3q28192 nomenclature and were just being ignored by UCRM without the error message that was introduced actually responding with something other than "<null>" to each webhook.

 

THAT IS WHY WE UPGRADED TO 2.15.1 (PAYMENTS WERENT MATCHING AT ALL IN THE VERSION THAT WAS TESTED AND QA READY ON 2/15/19)

 

Now after the upgrade only payments/subscriptions created with Stripe AFTER THE UPGRADE properly match a transaction.

 

I have the JSON for each of the 100 transactions loaded into SOAP UI ready to post to the webhook but I need to know what field I need to interject or change in these to make them match the transactions that were created in UCRM before the upgrade.

 

If this prod.log is where all exceptions that are ignored by UCRM are logged, then I suggest adding the prod.log to the selection in System->Settings->Logs and allow us to easily submit this data to UBNT for troubleshooting without having to go digging into containers.

 

You also need to allow UCRM users some sort of access to the codebase for the payment modules and the changes you guys make to the code that affects us, such as moving the stripe module to a plugin with revision history in GIT where we can clearly see what you change so that we can make corrective actions on our side when necessary.

 

 

Ubiquiti Employee
Posts: 1,476
Registered: ‎03-21-2016
Kudos: 244
Solutions: 161

Re: Stripe Refunds Webhook Not Working

Hello @drphipps,

 

I double checked and the error is fixed since UCRM 2.15.0-beta7 and there is no regression. There is actually empty line at Charge.php:84 since 2.15.0 stable, so the error could not have been generated there.

Further Charge.php has nothing to do with ACH payments or subscriptions payments, this class handles only regular one-time credit card payments.

Any errors that would happen with processing ACH one-time payments or CC/ACH subscription would propably appear in ChargeSucceededEventHandler in UCRM 2.15.1. If you see anything like that in your prod.log, please let us know.

 

If you can send me JSON file of an ACH payment that still does not match for you, I can look into it further.

 

Thank you for the suggestion with prod.log, this is something we're already planning to improve.

New Member
Posts: 44
Registered: ‎10-07-2015
Kudos: 36

Re: New UCRM version 2.15.1 released

System => Tools menu missing after upgrade to 2.15.1



Only options in System => are 



Settings

Organizations

Service Plans & Product

Billing

Have to use the search to get to backups now