I have been trying to build a custom Woocommerce Cart API endpoint, I implemented the add to cart feature but I have ended up facing an issue with shipping taxes.
I want to calculate shipping taxes (especially for flexible_shipping_single) but my code isn't working :
$shippings = [];
if (isset($request["shipping_lines"]) && !empty($request["shipping_lines"])) {
foreach ($request["shipping_lines"] as $shipping_line) {
$shippings[] = $shipping_line["method_id"];
}
WC()->session->set('chosen_shipping_methods', $shippings);
}
$cart->calculate_totals();
Here's my request (I removed some lines to minimize the size)
{
"line_items": [
{
"product_id": 15071,
"variation_id": 0,
"quantity": 9
}
],
"shipping": {
"first_name": "John",
"last_name": "Doe",
"address_1": "969 Market",
"address_2": "",
"city": "San Francisco",
"state": "CA",
"postcode": "94103",
"country": "US"
},
"shipping_lines": [
{
"method_id": "flexible_shipping_single",
"method_title": "Flexible Shipping"
}
]
}
The issue:
The issue was in the param "state": CA that doesn't exist in the state's list of the shipping zones, So the calculate_shipping() couldn't find the shipping package related to the shipping method selected by the user and its rates, which means that the flexible_shipping_single won't work, instead, it sets back the default shipping method, in my case wc_pickup_store
Related
I'm new with STRIPE, and I've been reading the documentation for STRIPE, and was task to create a list of payouts to a connected account (type is standard). Also, I have to show the details, under those PAYOUT, all the payments included in it.
However I can't see any relation to PAYOUTS with PAYMENT INTENTS/CHARGES, is it possible to know all those payments included in the PAYOUTS ? We are creating STANDARD connect accounts for our users.
I had the same challenge, and had to go thru 4 supporters, tell my needs over and over again, before i finally got the right hint and could complete my checks and cron jobs. I provide my solution here to save others the same experience:
$po = 'po_sadfahk.....'; // payout id (i do a loop of payouts)
\Stripe\Stripe::setApiKey($stripeSecretKey);
$balanceTransactions = \Stripe\BalanceTransaction::all([
'payout' => "$po",
'type' => 'charge',
'limit' => 100, // default is 10, but a payout can have more pi's
'expand' => ['data.source'],
]);
foreach ($balanceTransactions->data as $txn) {
// my invoice id is added in description when creating the payment intent
echo "Invoice: {$txn->description}\n";
echo "Created: {$txn->created}\n";
echo "Available: {$txn->available_on}\n";
// in source we find the pi_id, amount and currency for each payment intent
$charge = $txn->source;
echo "pi: {$charge->payment_intent}\n";
$amount = $charge->amount/100;
echo "$amount {$charge->currency}\n";
}
Output (cropped to relevant data):
{
"object": "list",
"data": [
{
"id": "txn_1ISOaSGqFEoKRtad...",
"object": "balance_transaction",
"amount": 25000,
"available_on": 1615680000,
"created": 1615131127,
"currency": "dkk",
"description": "Invoice 44",
...
"fee": 530,
"fee_details": [
{
"amount": 530,
"application": null,
"currency": "dkk",
"description": "Stripe processing fees",
"type": "stripe_fee"
}
],
...
"source": {
"id": "ch_1ISOaRGqFEoKR...",
"object": "charge",
"amount": 25000,
...
"paid": true,
"payment_intent": "pi_1ISOa3GqFE...", // here we go!
"payment_method": "pm_1ISOaRGqFE...",
"payment_method_details": {
"card": {
"brand": "visa",
...
},
"type": "card"
},
...
},
"status": "available",
"type": "charge"
}
],
"has_more": false,
"url": "/v1/balance_transactions"
}
Kudos to Kim for his answer. I also went through a number of supporters in Stripe to no avail. His post sorted me out.
The code below is a mere Python 3.10 translation from Kim's code above
po = 'po_<some_payment_id>'
balanceTransactions = stripe.BalanceTransaction.list(
payout=po,
type='charge',
limit=100,
expand=['data.source']
)
for txn in balanceTransactions.data:
print("Invoice: {0}".format(txn.description))
print("Created: {0}".format(txn.created))
print("Available: {0}".format(txn.available_on))
charge = txn.source
print("pi: {0}".format(charge.payment_intent))
amount = charge.amount/100
print("{0} {1}".format(amount, charge.currency))
I'm not sure you'll have that access for a Standard Account, but if it you do, you'll be able to list all of the Balance Transactions associated with that Payout, which will have a reference to the Payment Intent in the source field for any Payment Intents.
i'm using Paypal PHP SDK (in Laravel) to prepare a payment. At the moment, that payment looks like this:
{
"intent":"sale",
"payer":{
"payment_method":"paypal"
},
"redirect_urls":{
"return_url":"http://website.lab/payment/paypal/success",
"cancel_url":"http://website.lab/payment/paypal/cancel"
},
"transactions":[
{
"amount":{
"currency":"EUR",
"total":"223",
"details":{
"shipping":"0",
"subtotal":"273"
}
},
"description":"...",
"item_list":{
"items":[
{
"name":"product 8",
"currency":"EUR",
"quantity":21,
"sku":"w9",
"price":"13.00"
}
],
"shipping_address":{
"city":"...",
"postal_code":"...",
"country_code":"...",
"recipient_name":"...",
"line1":"..."
}
}
}
]
}
As you can see there are 50€ missing from the total to the subtotal and this cause this error
400{"name":"VALIDATION_ERROR","details":[{"field":"transactions[0].amount","issue":"Transaction amount details (subtotal, tax, shipping) must add up to specified amount total"}],"message":"Invalid request - see details","information_link":"https://developer.paypal.com/docs/api/payments/#errors","debug_id":"91d27597e954"}
Now looking to the Paypal SDK i'm not able to find any sort of method/Object that can tell Paypal to add a discount to the subtotal.
Any help will be appreciate, i really can't find any resource on the web that can solve this problem
You can add an item to your "item_list" with a negative value to the transaction:
{
"name": "Discount",
"price": "-50",
"currency": "EUR",
"quantity": "1"
}
I'm using the WooCommerce REST API (http://woocommerce.github.io/woocommerce-rest-api-docs/#introduction) and have added a new field (shipping_phone) to the checkout page using their example here:
https://docs.woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/
This new field appears on the checkout page and I can populate this and it is saved to my order - here's how it appears in the WordPress admin page for an order:
I'm now trying to download the Order with the shipping_phone data by using this GET request:
/wp-json/wc/v1/orders/3454
but the shipping_phone field isn't included in the downloaded fields. Here's the Shipping fields from the GET response:
"shipping": {
"address_1": "45 Jones Road",
"address_2": "",
"city": "Bondi",
"company": "BS Consulting Pty Ltd",
"country": "AU",
"first_name": "Betty",
"last_name": "Sanders",
"postcode": "2026",
"state": "NSW"
},
It's also not located anywhere else in the JSON data. How do I do a GET request to get an Order which includes this new custom field?
You can use the WooCommerce REST API v2 or later to get the Order Meta Data which includes these custom fields. If you GET an Order:
wp-json/wc/v3/orders/3454
it will include a meta_data array with these custom field values:
"meta_data" :
[
{
"id" : 4672,
"key" : "_shipping_method",
"value" : [ "flat_rate:1" ]
},
{
"id" : 4673,
"key" : "_shipping_phone",
"value" : "08 9632 7412"
}
]
I am developing an e-commerce mobiloe application using magento 2 rest apis only.This is the flow for making the REST API calls for order placement.
1.Create a cart
api -->{{url}}/index.php/rest/V1/carts/mine
This api will return a unique cart id
2.Add products to cart
api --> {{url}}/index.php/rest/V1/carts/mine/items
body ->
{
"cart_item": {
"quote_id": cartId,
"sku": skuName,
"qty": 1
}
}
3. Estimate Shipping Methods
url --> {{url}}/index.php/rest/V1/carts/mine/estimate-shipping-methods
body ->
{
"address": {
"region": "Trivandrum",
"region_id": 12,
"region_code": "CA",
"country_id": "IN",
"street": [
"Amstor house",
"Eramam"
],
"telephone": "5656565454",
"postcode": "670390",
"city": "Kazhakuttam",
"firstname": "Peter",
"lastname": "K",
"same_as_billing": 0,
"save_in_address_book": 0
}
}
This will return all possible shipping methods based on shipping address.In my case the result is
[
{
"carrier_code": "freeshipping",
"method_code": "freeshipping",
"carrier_title": "Free Shipping",
"method_title": "Free",
"amount": 0,
"base_amount": 0,
"available": true,
"error_message": "",
"price_excl_tax": 0,
"price_incl_tax": 0
}
]
4)Save shipping information
url --> {{url}}/index.php/rest/V1/carts/mine/shipping-information
body data ->
{
"addressInformation": {
"shipping_address": {
"region": "Trivandrum",
"region_id": 12,
"region_code": "CA",
"country_id": "IN",
"street": [
"Amstor house",
"Eramam"
],
"telephone": "5656565454",
"postcode": "670390",
"city": "Kazhakuttam",
"firstname": "Peter",
"lastname": "K",
},
"billing_address": {
"region": "Trivandrum",
"region_id": 12,
"region_code": "CA",
"country_id": "IN",
"street": [
"Amstor house",
"Eramam"
],
"telephone": "5656565454",
"postcode": "670390",
"city": "Kazhakuttam",
"firstname": "Peter",
"lastname": "K",
},
"shipping_method_code": "freeshipping",
"shipping_carrier_code": "freeshipping"
}
}
This will return all possible payment methods. Here i am using paypal_express for payment.
5. Payment using paypal plugin
Here i will pay the amount using paypal cordova plugin.Also configured the IPN [{{url}}/paypal/ipn/]in paypal account
This api will return the following data,
{
"client": {
"environment": "sandbox",
"paypal_sdk_version": "2.14.4",
"platform": "Android",
"product_name": "PayPal-Android-SDK"
},
"response": {
"create_time": "2016-11-19T05:25:46Z",
"id": "PAY-5VS11410F5341972MLAX6ETA",
"intent": "sale",
"state": "approved"
},
"response_type": "payment"
}
5.Save payment and place order
url --> {{url}}/index.php/rest/V1/carts/mine/payment-information
data ->
{
"cartId": 3,
"billingAddress": {
"region": "Trivandrum",
"region_id": 12,
"region_code": "CA",
"country_id": "IN",
"street": [
"Amstor house",
"Eramam"
],
"telephone": "5656565454",
"postcode": "670390",
"city": "Kazhakuttam",
"firstname": "Peter",
"lastname": "K"
},
"paymentMethod": {
"method": "paypal_express"
}
}
But this api will returning
{
"message": "PayPal gateway has rejected request. Invalid token (#10410: Invalid token)."
}
Is there any api missing in the above flow for capturing payments.Please help me.
Paypal Express payment method doesn't support online capturing. There is no way to get a full order creation flow like on Checkout via Magento API interface. It is impossible to change the order state and process payments. As a workaround try the following:
Create a custom payment method
Enable for REST API only(Not on website checkout page)
While making payment using rest api use this method (after successful payment using you android/ios SDK)
After placing the order make send transaction id(PAY-xxxxx) return by paypal sdk payment to save trasaction.(tell your server side tio implement this call).
I am writting a complete atrticle regarding this step by step. I will let you know when it is done.
Place Order by PayPal Rest API
For the Place order by the Paypal rest API, you need an active cart with shipping and billing address
By default, we need to follow the few setups for placing the order
• Step 1. Create an empty cart
• Step 2. Add products to the cart
• Step 3. Set the shipping address
• Step 4. Set billing address
• Step 5. Set the delivery method
• Step 6. Apply a coupon (if you have)
• Step 7. Set the payment method
• Step 8. Place order
After steps 6 follow below APIs
We need to call the below APIs one by one for placing the order with Paypal
Create Paypal Express Token
URL : {you website
url}/rest/default/V1/paypalapi/createpaypalexpresstoken
Method: POST
Set Bearer Token in the Hearer (if customer ) for the guest user no need to set it
Content-type : JSON
Body For guest users:
{
"cart_id":"5QWFYZdyccucvgD2QMLDCp5fhjmaH2xg",
"cancel_url":"cancel_url",
"return_url":"return_url"
}
Body For Customer user:
{
"cart_id": 22,
"cancel_url": "cancel_url",
"return_url": "return_url"
}
You will get the response like this :
[
{
"code": 200,
"token": "EC-4MD50688YD296870K",
"paypal_urls":{
"start": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-4MD50688YD296870K&useraction=commit",
"edit": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&useraction=continue&token=EC-4MD50688YD296870K"
}
}]
Explanation
you need to redirect the customer to the {start URL } and after making the payment, PayPal will redirect the user with two params in the redirect URL "payer_id" and "token" Both values you need to call in the below API
Set Payment Method On Cart
URL : {you website
url}/rest/default/V1/paypalapi/setpaymentmethodoncart
Method: POST
Set Bearer Token in the Hearer (if customer ) for the guest user no
need to set it
Content-type : JSON
Body For guest users:
{
"cart_id": "5QWFYZdyccucvgD2QMLDCp5fhjmaH2xg",
"payer_id": "9T3GV67ZSL378",
"token": "EC-4MD50688YD296870K",
"payment_method": "paypal_express"
}
Body For Customer user:
{
"cart_id": 22,
"payer_id": "9T3GV67ZSL378",
"token": "EC-4MD50688YD296870K",
"payment_method": "paypal_express",
"customer_id": 141
}
You will get the response like this :
[
{
"code": 200,
"selected_payment_method": {
"code": "paypal_express",
"title": "PayPal Express Checkout"
}
}
]
Place Order
URL : {you website url}/rest/default/V1/paypalapi/placeorder
Method: POST
Set Bearer Token in the Hearer (if customer ) for the guest user no
need to set it
Content-type : JSON
Body For guest users:
{ "cart_id": "5QWFYZdyccucvgD2QMLDCp5fhjmaH2xg" }
Body For Customer user:
{ "cart_id": 22, "customer_id": 141 }
You will get the response like this :
[ { "code": 200, "order_number": 000000142 } ]
Here is the link to the Paypal Rest API module
https://github.com/santosh-gaggle/paypal-rest-api
In case someone still looking the solution.
In the time I'm answering this, You will need to create a Magento 2 module to process the payment ID.
After you receive the response from in example Paypal android SDK.
Below is the JSON format that you can send to Magento endpoint :
for logged user : PUT /V1/carts/mine/order
for guest : PUT /V1/guest-carts/:cartId/order
Referrence : http://devdocs.magento.com/swagger
The "paypal_express_payment_payload" is just a custom attribute to hold the paypal payment response previously from android SDK.
{
"paymentMethod": {
"method": "paypal_express",
"additional_data": {
"paypal_express_payment_payload": "{\"create_time\":\"2017-06-15T23:13:52Z\",\"id\":\"PAY-2LB41725NU654612TLFBRIUQ\",\"intent\":\"sale\",\"state\":\"approved\"}"
}
}
}
To process the "paypal_express_payment_payload" data, you can implement a Interceptor in your Magento 2 module :
di.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Paypal\Model\Express">
<plugin name="mymodule_magento_paypal_model_express_plugin"
type="Mycompanyorpersonal\Mymodule\Plugin\Paypal\Model\Express"
sortOrder="99999"
disabled="false" />
</type>
</config>
Mycompanyorpersonal\Mymodule\Plugin\Paypal\Model\Express.php
You can find the full PHP codes in my following gist : https://gist.github.com/feelinc/de817030e00adc7ff7001de1807c1835
If you use the below to run a post query replace runPostQuery with your curl request. this will pass a token that already has been successful to magento 2.
$payment['paymentMethod'] = ['method' =>'paypal_express',
'additional_data' => array (
'paypal_express_checkout_token' => $request->query->get('token'),
'paypal_express_checkout_redirect_required' => false,
'paypal_express_checkout_payer_id' => $request->query->get('PayerID')
)];
$completedPayment = $this->runPostQuery('carts/mine/payment-information', $headers, json_encode($payment));
You will need to create a plugin to add the last transaction id to the payment see the above comment, but the above payload to payment-information will allow you to get past _placeOrder function in Paypal\Model\Express.php
The paypal_express_checkout_token is the token passed back to the browser from paypal same as PayerId this allows to check the payment, which will return successful and not require a redirect, but is not the payment reference just the action token.
I'm using UPS api(JSON) refer from the ups.com developer kit.
1)I need shipment rating list with "Residential Shipment".
2)I need Add shipment with "Residential Address".
I am add ResidentialAddressIndicator as 1 in ShipTo address.(I am refer from UPS doc.)
But it's failed.
2)Sample code:
...........
...........
"ShipTo": {
"Name": "Ship To Name",
"AttentionName": "Ship To Attn Name",
"Phone": {
"Number": "1234567890"
},
"Address": {
"AddressLine": "195 N main st",
"City": "Sebastopol",
"StateProvinceCode": "CA",
"PostalCode": "95472",
"CountryCode": "US",
"ResidentialAddressIndicator":"1" //I am refer from UPS doc.
}
},
..........
..........
Your answers are highly appreciated!
in the <ShipTo> element add <Residential Address/>, you can find this in the Shipping Package XML Developers Guide that UPS provides.