Woocommerce + Payment (PayPal) - Securely update order status + get transaction ID - php

I am currently implementing the Paypal Payment Gateway into my shop.
I added an return URL inside my paypal sandbox account.
Payment steps so far:
Create an order
Create a payment via WC_Gateway_Paypal class
Redirect to paypal site login & process payment
redirect to return_url on succes
Sample code:
function create_order()
{
$order = wc_create_order();
$product = wc_get_product(55);
$order->add_product($product, 1);
$address = array(
'first_name' => 'John',
'last_name' => 'Doe',
'company' => '',
'email' => 'john#doe.com',
'phone' => '111111',
'address_1' => '',
'address_2' => '',
'city' => '',
'state' => '',
'postcode' => '',
'country' => ''
);
$order->set_address($address, 'billing');
$order->set_address($address, 'shipping');
$order->calculate_totals();
$order->set_payment_method('paypal');
$paypal = new WC_Gateway_Paypal();
$paymentdetails = $paypal->process_payment($order->get_id());
return $paymentdetails;
}
In $paymentdetails I return the paypal URL where I redirect the customer to.
After successful payment the customer gets redirect from paypal to: http://mypage.com/56/?key=wc_order_59d24a26d4ccb&utm_nooverride=1
Now I want to update my order. I know that I could just read the ID and the key of the order from the redirect URL, but wouldnt that be an security issue? If someone knows the ID or the key he could just trigger a GET to my site and update his order without actual payment.
Is there a better way to accomplish this? Or do I just have to use the key=wc_order_59d24a26d4ccb instead of the ID and be careful not to send the key to the frontend?
Also, I am not getting any transaction_id, $order->get_transaction_id(); is empty after successful payment. Is this because I am developing on my local machine / with a sandbox account?

This is most likey because you are developing on a local machine.
The paypal integration does a lot of stuff in the background (exchanging tokens, updating orders, etc...). When you create a payment, paypal gets your local dev URL (i.e. http://localhost/something) but cannot reach it because you are behind a router. Try to move the installation to a server or webspace and try again, it should work.

Related

WooCommerce / Stripe: Trouble trying to pass a Stripe Customer ID through WC_Order

I'm having trouble passing a Stripe Customer ID directly to a WC_Order object. I have tried passing it through the payment gateway metadata via the set_payment_method function however nothing I try seems to work.
I am trying to complete an entire order programmatically in order to migrate another system over to WordPress. We're trying to do this with WC Subscription objects which inherit from WC_Order.
Let me know if there is a good solution to this. Thank you!
Here's a bit of code to demonstrate what I'm basically trying to do:
$order = wc_create_order(['customer_id' => $user_id]);
$user = get_user_by( 'ID', $user_id );
$order->add_product( $product, 1 );
$payment_gateways = WC()->payment_gateways->payment_gateways();
$order->set_payment_method($payment_gateways['stripe'], [
'customer_id' => 'cus_XXXXXXXXXXXXXX' // this part right here, doesnt seem to work
]);
// $order->set_payment_method($payment_gateways['stripe'], [
// 'stripe_customer_id' => 'cus_XXXXXXXXXXXXXX' // also doesnt seem to work
// ]);
The ending result was that the order could not be completed and transactions do not come through to our Stripe account either.
Documentation on the set_payment_method function is very limited and provides no additional information on supported data that can be passed.
WC Subscriptions API Reference
The payment meta array can consist of 3 keys and their values. They are inserted into 3 tables as mentioned in the below example.
$payment_meta = array(
'user_meta' => array(
'payment_usermeta_key' => 'Test payment user meta value',
'customer_id', 'cus_XXXXXXXXXXXXXX'
),
'post_meta' => array(
'payment_post_meta_key' => 'Test payment post meta value'
),
'options' => array(
'payment_related_options_key' => 'Test payment options value'
)
)

Laravel Stripe MultiPlan Subscription

I want to add Add On to my subscription. Thus i follow this MultiPlan in Laravel doc. For every new subscription, new stripe product are create (means every plan have different product. including the addon). User need to subscribe to any subscription before subscript to the addon. There are no error, but the Subscription DB from stripe for the current subscription will return null quantity and null stripe_plan. Then create error from that database as i cant call the current subscription. Why does the stripe does that? or am I surpose to create new plans under the same product id in Stripe?
My code to create stripe product and plan
$stripe = new StripeClient(env('STRIPE_SECRET'));
$product_stripe = $stripe->products->create([
'name' => $request->service_name,
]);
$plan_stripe = $stripe->plans->create([
// 'id' => $stripe_plan,
'nickname' => $request->service_name,
'product' => $product_stripe['id'],
'amount' => $request->price*100,
'currency' => 'usd',
'interval' => $request->period,
'interval_count' => $request->period_num,
]);
This is my code to subscribe to addon
$user = auth()->user();
$user->subscription('default')->addPlanAndInvoice('plan_stripe_id', 'quantity');
Note that default is the user current subscription.

Stripe Checkout for recurring donations of variable amounts

I am trying to use Stripe Checkout to allow users to set up a monthly recurring donation for an amount of their choosing. When I set up the Session, it provides the correct inputs to the Stripe form, however when I look in Subscriptions in the back end of Stripe, nothing is created, and it seems to just take a single payment. Here is my code:
$checkout_values['success_url'] = $success_url;
$checkout_values['cancel_url'] = $cancel_url;
$checkout_values['payment_method_types'] = ['card','sepa_debit'];
$checkout_values['mode'] = 'subscription';
$checkout_values['metadata']['order_id'] = $order_id;
//Single line item for the dynamically created subscription and price info
$line_item = [
'price_data' => [
'recurring' => [
'interval' => 'month',
'interval_count' => 1
],
'currency' => $order->get_currency(),
'product_data' => [
'name' => $item->get_name()
],
'unit_amount' => $item_total
],
'quantity' => 1,
];
$checkout_values['line_items'][] = $line_item;
Maybe I need to create a subscription in Stripe and tie that in? In which case why doesn't it give me an error?
you don't need to explicitly create a subscription object. If you use Stripe Checkout, a subscription will be automatically created when your customer completed the payment flow in your checkout page.
You might want to firstly check if you are viewing the right mode (either Live or Test), and then take a look at the Dashboard Events to confirm subscription related events. You application can also listen to webhook events to get notified.

Why is PayPal GetVerifiedStatus API not working for certain account

I am using this library to verify PayPal users through email ID. The API I am using is GetVerifiedStatus. The developer of the library provides an email address in the code and it works fine. The code returns the status as "VERIFIED" for his email ID.
However, whenever I try to use my email ID, it shows "Cannot determine PayPal Account status" with ErrorID --580023. I tried another person's email ID and still it does not work. I am sure there is no typo in the email, firstname, lastname fields.
Seems, these links addresses the same issue.
PayPal GetVerifiedStatus not working with other accounts and Does PayPal's GetVerifiedStatus `belong' to the api caller's country?
This is the code that comes with the library. (added my paypal email ID and name)
require_once('../includes/config.php');
require_once('../autoload.php');
// Create PayPal object.
$PayPalConfig = array(
'Sandbox' => $sandbox,
'DeveloperAccountEmail' => $developer_account_email,
'ApplicationID' => $application_id,
'DeviceID' => $device_id,
'IPAddress' => $_SERVER['REMOTE_ADDR'],
'APIUsername' => $api_username,
'APIPassword' => $api_password,
'APISignature' => $api_signature,
'APISubject' => $api_subject,
'PrintHeaders' => $print_headers,
'LogResults' => $log_results,
'LogPath' => $log_path,
);
$PayPal = new angelleye\PayPal\Adaptive($PayPalConfig);
// Prepare request arrays
$GetVerifiedStatusFields = array(
'EmailAddress' => 'xxxxxx', // Required. The email address of the PayPal account holder.
'FirstName' => 'xxxxxx', // The first name of the PayPal account holder. Required if MatchCriteria is NAME
'LastName' => 'xxxxxx', // The last name of the PayPal account holder. Required if MatchCriteria is NAME
'MatchCriteria' => 'NAME' // Required. The criteria must be matched in addition to EmailAddress. Currently, only NAME is supported. Values: NAME, NONE To use NONE you have to be granted advanced permissions
);
$PayPalRequestData = array('GetVerifiedStatusFields' => $GetVerifiedStatusFields);
// Pass data into class for processing with PayPal and load the response array into $PayPalResult
$PayPalResult = $PayPal->GetVerifiedStatus($PayPalRequestData);
// Write the contents of the response array to the screen for demo purposes.
echo '<pre />';
print_r($PayPalResult);
I am not getting any idea why it is happening. Can anyone help please?
You are testing in sandbox mode. You must create sandbox accounts, either via https://developer.paypal.com/docs/classic/lifecycle/sb_about-accounts/#create-and-manage-sandbox-accounts or using the standard user flow on https://www.sandbox.paypal.com/us/home .

Magento: Redirect customer to third-party payment site

I'm currently creating my first custom checkout page in Magento. I've got a code that works - it creates an unpaid order, so the next step is to redirect the customer to the third-party payment site based on the selected payment method.
After some research it seems like there's a parameter called redirectUrl which I should be able to get somehow, but I can't really figure out how.
If I'm all wrong then please point me back on track! Thank you in advance.
<?php
require_once 'app/Mage.php';
Mage::app();
$quote = Mage::getModel('sales/quote')->setStoreId(Mage::app()->getStore('default')->getId());
// guest order
$quote->setCustomerEmail('customer#example.com');
// add sample product
$product = Mage::getModel('catalog/product')->load(8);
$buyInfo = array(
'qty' => 1,
);
$quote->addProduct($product, new Varien_Object($buyInfo));
$addressData = array(
'firstname' => 'Test',
'lastname' => 'Test',
'street' => 'Sample Street 10',
'city' => 'Somewhere',
'postcode' => '123456',
'telephone' => '123456',
'country_id' => 'SE'
);
$billingAddress = $quote->getBillingAddress()->addData($addressData);
$shippingAddress = $quote->getShippingAddress()->addData($addressData);
$shippingAddress->setCollectShippingRates(true)->collectShippingRates()->setShippingMethod('flatrate_flatrate')->setPaymentMethod('checkmo');
$quote->getPayment()->importData(array('method' => 'checkmo'));
$quote->collectTotals()->save();
$service = Mage::getModel('sales/service_quote', $quote);
$service->submitAll();
$order = $service->getOrder();
echo 'Created order #' . $order->getIncrementId();
?>
In the sample code you are using Magento classes into a standalone PHP file. In this way, Magento redirects will not work, since it is a method from Mage_Core_Controller_Front_Action. You have to be using Magento controllers to try this redirect way.
Anyway, you can use the PHP header function: header("Location: http://somepayment.com/complexUrl"); die;

Categories