Trying to update a paymentIntent in stripe getting 500 error - php

I'm stuck on a "simple" stripe integration problem. I have a checkout page where the amount can change on the checkout page, so the paymentIntent needs to change after the amount does. I created a short php app that is IDENTICAL to the one that successfully creates the paymentIntent, but now I'm updating the paymentIntent. I successfully pass in the new cost and the payment intent id to the app. But when I execute the ONE LINE of code to do the update, the fetched php doc throws an error 500. I comment out that ONE LINE and I don't get the error. I tried uploading it to a secure server thinking that was it (but I can run the create.php on my localhost without a problem) that didn't fix it either. I've been working on this for 10 hours and need to get it done tonight. Do you think you could help? here's the code:
\Stripe\Stripe::setApiKey('sk_test_xxx...'); // I have the correct secret key
header('Content-Type: application/json');
try {
// retrieve JSON from POST body
$json_str = file_get_contents('php://input');
$json_obj = json_decode($json_str);
$cost = $json_obj->c;
$paymentId = $json_obj->pi;
\Stripe\PaymentIntent::update(
$paymentId,
['amount' => $cost]
);
$output = [
'amount' => $stripe->amount,
];
echo json_encode($output); // to verify that it changed it
} catch (Error $e) {
http_response_code(500); // even if I comment this line out, i get error 500
echo json_encode(['error' => $e->getMessage()]);
}

::solved::
Ok, my stupid fault. The docs are a little unclear. It has you store the client_secret to actually do the charge later. To update a paymentIntent, you need to pass the paymentIntentId. They start with the same long string of letters and I thought they were the same.

Related

Stripe Webhook Testing Issue - Test payments don't call the webhook

I'm trying to integrate Stripe to accept payments on a website. I've come to the point where pretty much everything works from the client's perspective - test payments go through, everything is integrated and I can do stuff on payment intent succeeded (on the client). However, I can only detect that on the front-end.
Now, I want to show customer some sensitive data when payment is completed. I can't do it on front end - because then client does not even have to pay for that. I need to use webhooks.
So, I've created a sample webhook like this:
require_once 'stripe-php-7.97.0/init.php';
$endpoint_secret = 'endpoint_secret_code';
$payload = #file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;
try {
$event = \Stripe\Webhook::constructEvent(
$payload, $sig_header, $endpoint_secret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
http_response_code(400);
exit();
}
ob_flush();
ob_start();
var_dump($event);
file_put_contents("dump.txt", ob_get_flush());
// Handle the event
switch ($event->type) {
case 'payment_intent.succeeded':
$paymentIntent = $event->data->object;
var_dump($event->type);
// ... handle other event types
default:
echo 'Received unknown event type ' . $event->type;
}
http_response_code(200);
I've also created a webhook in the Stripe dashboard, like this:
However, based on the payment amount, I need to do something on this web hook - create a session, store data into the database and so on and so on. I've made it possible with Stripe CLI to test this webhook. However, how to test it using the test payments on the actual page? I have no idea how to do that - it does not work at the moment and without it, I can't be sure that it will work properly once everything goes live until I properly test it like this.
Does anyone have any tips, tutorials, or any kind of help to solve this? I'm pretty much stuck on it so any help would be greatly appreciated.

How to use PayPal Express Payments (PHP)

I am using the PayPal PHP SDK found here: https://github.com/paypal/Checkout-PHP-SDK
And I am somewhat puzzled in terms of how to complete the process.
On the outset this seems quite simple:
Setup your credentials
Create the Order
Check the result, and re-direct to approval link
User makes a payment and is sent to the SUCCESS link that you would have set.
i.e. http://example.com/pay/complete/paypal?token=8UK32254ES097084V&PayerID=SEQNPLB2JR9LY
And this is where things get a bit shakey.
Conveniently, a token and a PayerID is returned.
And according to the documentation, you now need to "Capturing the Order" and the following code is provided:
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
// Here, OrdersCaptureRequest() creates a POST request to /v2/checkout/orders
// $response->result->id gives the orderId of the order created above
$request = new OrdersCaptureRequest("APPROVED-ORDER-ID");
$request->prefer('return=representation');
try {
// Call API with your client and get a response for your call
$response = $client->execute($request);
// If call returns body in response, you can get the deserialized version from the result attribute of the response
print_r($response);
}catch (HttpException $ex) {
echo $ex->statusCode;
print_r($ex->getMessage());
}
What is confusing is that the OrdersCaptureRequest requires an "APPROVED-ORDER-ID"
But all that has been returned is a "token" and a "PayerID".
So my question is, what is this APPROVED-ORDER-ID, and where do I get it?
Thank you!
what is this APPROVED-ORDER-ID, and where do I get it
At that moment, sourced from token= . It should correspond to an Order Id you received in the response to your step 2 ("Create the Order")
For step 3, it is better to use no redirects whatsoever. Instead, implement this front-end UI, which offers a far superior in-context experience that keeps your site loaded in the background: https://developer.paypal.com/demo/checkout/#/pattern/server
There is no reason for a modern website to be redirecting unnecessarily

PHP Azure SDK Service Bus returns Malformed Response

I'm working on trace logger of sorts that pushes log message requests onto a Queue on a Service Bus, to later be picked off by a worker role which would insert them into the table store. While running on my machine, this works just fine (since I'm the only one using it), but once I put it up on a server to test, it produced the following error:
HTTP_Request2_MessageException: Malformed response: in D:\home\site\wwwroot\vendor\pear-pear.php.net\HTTP_Request2\HTTP\Request2\Adapter\Socket.php on line 1013
0 HTTP_Request2_Response->__construct('', true, Object(Net_URL2)) D:\home\site\wwwroot\vendor\pear-pear.php.net\HTTP_Request2\HTTP\Request2\Adapter\Socket.php:1013
1 HTTP_Request2_Adapter_Socket->readResponse() D:\home\site\wwwroot\vendor\pear-pear.php.net\HTTP_Request2\HTTP\Request2\Adapter\Socket.php:139
2 HTTP_Request2_Adapter_Socket->sendRequest(Object(HTTP_Request2)) D:\home\site\wwwroot\vendor\pear-pear.php.net\HTTP_Request2\HTTP\Request2.php:939
3 HTTP_Request2->send() D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\Common\Internal\Http\HttpClient.php:262
4 WindowsAzure\Common\Internal\Http\HttpClient->send(Array, Object(WindowsAzure\Common\Internal\Http\Url)) D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\Common\Internal\RestProxy.php:141
5 WindowsAzure\Common\Internal\RestProxy->sendContext(Object(WindowsAzure\Common\Internal\Http\HttpCallContext)) D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\Common\Internal\ServiceRestProxy.php:86
6 WindowsAzure\Common\Internal\ServiceRestProxy->sendContext(Object(WindowsAzure\Common\Internal\Http\HttpCallContext)) D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\ServiceBus\ServiceBusRestProxy.php:139
7 WindowsAzure\ServiceBus\ServiceBusRestProxy->sendMessage('<queuename>/mes…', Object(WindowsAzure\ServiceBus\Models\BrokeredMessage)) D:\home\site\wwwroot\vendor\microsoft\windowsazure\WindowsAzure\ServiceBus\ServiceBusRestProxy.php:155
⋮
I've seen previous posts that describe similar issues; Namely:
Windows Azure PHP Queue REST Proxy Limit (Stack Overflow)
Operations on HTTPS do not work correctly (GitHub)
That imply that this is a known issue regarding the PHP Azure Storage libraries, where there are a limited amount of HTTPS connections allowed. Before requirements were changed, I was accessing the table store directly, and ran into this same issue, and fixed it in the way the first link describes.
The problem is that the Service Bus endpoint in the connection string, unlike Table Store (etc.) connection string endpoints, MUST be 'HTTPS'. Trying to use it with 'HTTP' will return a 400 - Bad Request error.
I was wondering if anyone had any ideas on a potential workaround. Any advice would be greatly appreciated.
Thanks!
EDIT (After Gary Liu's Comment):
Here's the code I use to add items to the queue:
private function logToAzureSB($source, $msg, $severity, $machine)
{
// Gather all relevant information
$msgInfo = array(
"Severity" => $severity,
"Message" => $msg,
"Machine" => $machine,
"Source" => $source
);
// Encode it to a JSON string, and add it to a Brokered message.
$encoded = json_encode($msgInfo);
$message = new BrokeredMessage($encoded);
$message->setContentType("application/json");
// Attempt to push the message onto the Queue
try
{
$this->sbRestProxy->sendQueueMessage($this->azureQueueName, $message);
}
catch(ServiceException $e)
{
throw new \DatabaseException($e->getMessage, $e->getCode, $e->getPrevious);
}
}
Here, $this->sbRestProxy is a Service Bus REST Proxy, set up when the logging class initializes.
On the recieving end of things, here's the code on the Worker role side of this:
public override void Run()
{
// Initiates the message pump and callback is invoked for each message that is received, calling close on the client will stop the pump.
Client.OnMessage((receivedMessage) =>
{
try
{
// Pull the Message from the recieved object.
Stream stream = receivedMessage.GetBody<Stream>();
StreamReader reader = new StreamReader(stream);
string message = reader.ReadToEnd();
LoggingMessage mMsg = JsonConvert.DeserializeObject<LoggingMessage>(message);
// Create an entry with the information given.
LogEntry entry = new LogEntry(mMsg);
// Set the Logger to the appropriate table store, and insert the entry into the table.
Logger.InsertIntoLog(entry, mMsg.Service);
}
catch
{
// Handle any message processing specific exceptions here
}
});
CompletedEvent.WaitOne();
}
Where Logging Message is a simple object that basically contains the same fields as the Message Logged in PHP (Used for JSON Deserialization), LogEntry is a TableEntity which contains these fields as well, and Logger is an instance of a Table Store Logger, set up during the worker role's OnStart method.
This was a known issue with the Windows Azure PHP, which hasn't been looked at in a long time, nor has it been fixed. In the time between when I posted this and now, We ended up writing a separate API web service for logging, and had our PHP Code send JSON strings to it over cURL, which works well enough as a temporary work around. We're moving off of PHP now, so this wont be an issue for much longer anyways.

Paypal IPN now returns INVALID - PHP code previously working fine

I'm using the following class to process the IPN data:
https://github.com/WadeShuler/PHP-PayPal-IPN (and it has been working fine for ages)
The last successfully processed payment was on September 28, the next IPN payment that came though on October 5 returned a response of INVALID, as has every payment since.
If I test in the IPN simulator, the message processes successfully.
Sandbox or Live, the response is INVALID. I would have thought the Sandbox would have a facility where I can review why a message was rejected as INVALID, but that doesn't seem to be the case? Would certainly have been the easy way to see the rejection reason, am I missing something?
The link that brings you to Paypal from my site is:
https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_ext-enter&redirect_cmd=_xclick&business=sales-facilitator#fydentry.com&item_name=QLD++%28Pacific+pines+secondary+Sat+25th+July+%29&item_number=FYD15000003&custom=0001000003&currency_code=AUD&amount=0.01&no_shipping=1&image_url=http://www.fydentry.com/img/follow-your-dreams-100.jpg&return=http://www.fydentry.com/entry-test.php&cancel_return=http://www.fydentry.com/entry-test.php&notify_url=http://www.fydentry.com/payback-test.php
The data posted back from Paypal is:
transaction_subject=0001000003&txn_type=web_accept&payment_date=07%3A05%3A07+Oct+15%2C+2015+PDT&last_name=buyer&residence_country=AU&pending_reason=multi_currency&item_name=QLD++%28Pacific+pines+secondary+Sat+25th+July+%29&payment_gross=&mc_currency=AUD&business=sales-facilitator%40fydentry.com&payment_type=instant&protection_eligibility=Ineligible&verify_sign=Acssfl2b2v1gxOK33TD2StcDhf-OAZxwix74kxFlSgpWMku6myuy.WFL&payer_status=verified&test_ipn=1&tax=0.00&payer_email=sales-buyer%40fydentry.com&txn_id=9BV63134E20871700&quantity=1&receiver_email=sales-facilitator%40fydentry.com&first_name=test&payer_id=FY3RYW98GNMXG&receiver_id=95FC3QCK53MHC&item_number=FYD15000003&handling_amount=0.00&payment_status=Pending&shipping=0.00&mc_gross=0.01&custom=0001000003&charset=windows-1252&notify_version=3.8&ipn_track_id=cfbd422d97d69
The response I send back to Paypal is:
cmd=_notify-validate&transaction_subject=0001000003&txn_type=web_accept&payment_date=07%3A05%3A07+Oct+15%2C+2015+PDT&last_name=buyer&residence_country=AU&pending_reason=multi_currency&item_name=QLD++%28Pacific+pines+secondary+Sat+25th+July+%29&payment_gross=&mc_currency=AUD&business=sales-facilitator%40fydentry.com&payment_type=instant&protection_eligibility=Ineligible&verify_sign=Acssfl2b2v1gxOK33TD2StcDhf-OAZxwix74kxFlSgpWMku6myuy.WFL&payer_status=verified&test_ipn=1&tax=0.00&payer_email=sales-buyer%40fydentry.com&txn_id=9BV63134E20871700&quantity=1&receiver_email=sales-facilitator%40fydentry.com&first_name=test&payer_id=FY3RYW98GNMXG&receiver_id=95FC3QCK53MHC&item_number=FYD15000003&handling_amount=0.00&payment_status=Pending&shipping=0.00&mc_gross=0.01&custom=0001000003&charset=windows-1252&notify_version=3.8&ipn_track_id=cfbd422d97d69
And the code in payback-test.php is:
<?php
include_once("f_common.php");
include_once("IpnListener.php");
use wadeshuler\paypalipn\IpnListener;
$listener = new IpnListener();
$listener->use_sandbox = true;
$dbh = open_db();
$res = 'UNKNOWN';
try {
$listener->requirePostMethod();
$verified = $listener->processIpn();
} catch (Exception $e) {
error_log($e->getMessage());
exit(0);
}
if ($verified) {
$res = "VERIFIED";
} else {
$res = "INVALID";
}
$stmt_debug = $dbh->prepare('INSERT INTO fyd_paypal_ipn (post_data, response_data, status, message_time) VALUES (:post_data, :response_data, :status, UTC_TIMESTAMP())');
$stmt_debug->execute(array(':post_data' => $listener->rawPostData, ':response_data' => $listener->debug_response, ':status' => $res));
?>
Note that for the purpose of this exercise, I also modified the IpnListener class so that I can get a copy of the response for debugging purposes.
At the top of the file in the variable declarations, I made $rawPostData public, and added this variable:
public $debug_response;
And store the value right before we use it:
$this->debug_response = $req;
if ($this->use_curl) {
$res = $this->curlPost($req);
} else {
$res = $this->fsockPost($req);
}
I'm assuming something has changed on the Paypal side to stop this working in the first place, but I can't see what it is, particularly as my response appears to be correct (identical), and I can't find anything in the Sandbox side that helps me identify why it is being regarded as invalid? Unfortunately the debug code at the bottom where I track the IPN post data and response is new, so I don't have an older (working!) set of messages to compare the contents to.
hummmm, since 1 october paypal change sha-1 to sha-2
https://www.paypal-knowledge.com/infocenter/index?page=content&id=FAQ1766&expand=true&locale=en_US
I've gotten to the bottom of it, it appears to be a certificate issue, combined with a script error.
My certificate file was out of date to the one currently in Wade's code. I spotted that and updated the certificate file yesterday. I've now verified that this was the root cause of my original failure.
However, while updating that, I also updated to the latest class - which was really just removing some deprecated code that I wasn't using and is no longer supported, but I missed one small change which broke things.
There's a line in the IpnListener class which sets the certificate location:
curl_setopt($ch, CURLOPT_CAINFO, dirname(dirname(__FILE__)) . '/cert/api_cert_chain.crt');
But the directory name ends up wrong on my server, and it can't find the certificate. The previous version of the class read:
curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cert/api_cert_chain.crt');
which worked. Now that I've changed it back, everything works again. Note that the domain I'm working from is set up in a sub-directory to my primary domain, which is possibly why the new code ends up pointing to the wrong place (one level above where I need it to be).
And I'm still confused as to why the IPN simulator worked, while the Sandbox and Live systems didn't.

authorize.net sandbox testing giving error

I am integrating authorize.net in PHP. I have used http://developer.authorize.net/integration/fifteenminutes/#custom this sdk for my development.
For testing, I have created an sandbox account. When I am executing the code - I'm getting below error:-
AuthorizeNet Error: Response Code: 3
Response Subcode: 1
Response Reason Code: 87
Response Reason Text: (TESTMODE) Transactions of this market type cannot be processed on this system.
How will I recover this issue and will make an successful test?
I have also checked payment processing using authorize.net. But not helped me so much.
Any help is appreciated.
EDIT:- code is below
function authorizeNet($options)
{
require_once '../anet_php_sdk/AuthorizeNet.php'; // Make sure this path is correct.
$transaction = new AuthorizeNetAIM('YOUR_API_LOGIN_ID', 'YOUR_TRANSACTION_KEY');
$transaction->amount = $options["gift_amt"];
$transaction->card_num = $options["card_no"];
$transaction->exp_date = $options["card_expiry"];
$response = $transaction->authorizeAndCapture();
if ($response->approved) {
echo "<h1>Success! The test credit card has been charged!</h1>";
echo "Transaction ID: " . $response->transaction_id;
die();
} else {
echo $response->error_message;
die();
}
}
in the place of YOUR_API_LOGIN_ID and YOUR_TRANSACTION_KEY - I placed correct information. Here I don't want to disclose so I haven't mentioned it here.
This error indicates that the account that you are using was created for Card Present (retail) transactions, but you are trying to integrate to our Card Not Present (e-commerce) APIs or vice versa. The only way to resolve this is to open a new sandbox account with the correct market type.

Categories