Charge tax using PayPal Subscriptions API - paypal

As an EU based seller I need to charge tax based on customer country tax rates and rules. That means that when I create subscription I need to specify either tax rate (percentage or amount) or have the ability to override subscription price. When using Stripe one just needs to specify tax_percent beside plan_id when creating subscription.
So far I wasn't able to do the same using PayPal Subscriptions API and their smart buttons. Tax rate can be set when creating plan but I need to be able to set tax percentage per subscription.
Sample smart button JS code:
paypal.Buttons({
createSubscription: function(data, actions) {
return actions.subscription.create({
'plan_id': 'P-2UF78835G6983425GLSM44MA',
// I'd like to be able to set tax rate here somehow
});
}
}).render('#paypal-button-container');
No luck setting up tax directly using Subscriptions API either:
curl -v -k -X POST https://api.sandbox.paypal.com/v1/billing/subscriptions \
-H "Accept: application/json" \
-H "Authorization: Bearer Access-Token" \
-H "Content-Type: application/json" \
-d '{
"plan_id": "P-2UF78835G6983425GLSM44MA",
"application_context": {
"brand_name": "example",
"user_action": "SUBSCRIBE_NOW",
"payment_method": {
"payer_selected": "PAYPAL",
"payee_preferred": "IMMEDIATE_PAYMENT_REQUIRED"
},
"return_url": "https://example.com/returnUrl",
"cancel_url": "https://example.com/cancelUrl"
}
}'
Am I missing something, thinking about this incorrectly or did PayPal "forgot" to implement basic thing like tax rate and therefore make their new subscriptions API unusable for VAT MOSS scenarios?

You can add the tax override to the plan node as shown below
<script>
paypal.Buttons({
createSubscription: function(data, actions) {
return actions.subscription.create({
'plan_id': 'YOUR_PLAN_ID_HERE', // Creates the subscription
'plan': {
'taxes': {
'percentage': '2.9',
'inclusive': false
}}
});
},
onApprove: function(data, actions) {
alert('You have successfully created subscription ' + data.subscriptionID); // Optional message given to subscriber
}
}).render('#paypal-button-container'); // Renders the PayPal button
</script>

It's an old topic and still not possible. PayPal doesn't support taxes with subscriptions. You can price your subscription so it has the VAT included in it. Mention that the price includes VAT before a user is redirected to payment.
I highly recommend not to implement the tax rules yourself. Better let a 3rd party API handle correct calculations.
https://vatstack.com/rates
https://quaderno.io/checkout
https://www.octobat.com/products/vat-gst-sales-tax-engine

Recently I found out that this is possible. Not sure if this is something added fairly recently or was this option there all along.
While creating a subscription you can override a plan and set the tax percentage inline.
curl -v -k -X POST https://api.sandbox.paypal.com/v1/billing/subscriptions \
-H "Accept: application/json" \
-H "Authorization: Bearer Access-Token" \
-H "Content-Type: application/json" \
-d '{
"plan_id": "#PLANID",
...
"plan": {
"taxes": {
"percentage": "19",
"inclusive": false
}
}
}'

Taxes seem to be included in the Plan entity.
https://developer.paypal.com/docs/subscriptions/full-integration/plan-management/#show-plan-details
curl -v -X GET https://api-m.sandbox.paypal.com/v1/billing/plans/P-2UF78835G6983425GLSM44MA \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <Access-Token>
{
"id": "P-2UF78835G6983425GLSM44MA",
"product_id": "PROD-6XB24663H4094933M",
"name": "Basic Plan",
"status": "ACTIVE",
"description": "Basic plan",
"billing_cycles": [
{
"frequency": {
"interval_unit": "MONTH",
"interval_count": 1
},
"tenure_type": "TRIAL",
"sequence": 1,
"total_cycles": 1
},
{
"pricing_scheme": {
"fixed_price": {
"currency_code": "USD",
"value": "10.0"
}
},
"frequency": {
"interval_unit": "MONTH",
"interval_count": 1
},
"tenure_type": "REGULAR",
"sequence": 2,
"total_cycles": 12
}
],
"payment_preferences": {
"auto_bill_outstanding": true,
"setup_fee": {
"currency_code": "USD",
"value": "10.0"
},
"setup_fee_failure_action": "CONTINUE",
"payment_failure_threshold": 3
},
----------------------------------------
"taxes": {
"percentage": "10.0",
"inclusive": false
},
----------------------------------------
"quantity_supported": false,
"create_time": "2020-02-26T07:01:04Z",
"update_time": "2020-02-26T07:01:04Z",
"links": [
{
"href": "https://api-m.sandbox.paypal.com/v1/billing/plans/P-2UF78835G6983425GLSM44MA",
"rel": "self",
"method": "GET"
},
{
"href": "https://api-m.sandbox.paypal.com/v1/billing/plans/P-2UF78835G6983425GLSM44MA",
"rel": "edit",
"method": "PATCH"
},
{
"href": "https://api-m.sandbox.paypal.com/v1/billing/plans/P-2UF78835G6983425GLSM44MA/deactivate",
"rel": "self",
"method": "POST"
}
]
}

Related

How to remove Upi(External wallet) from Razorpay - FLUTTER

I am using Razorpay for the payment in an e- commerce app, Actually in only need card payment in the payment method of razorpay. But how can i remove all the external payment from the options.
You can configure the payment methods of your choice on the Checkout section of the Payment Links to provide a highly personalized experience for your customers.
curl -u [YOUR_KEY_ID]:[YOUR_KEY_SECRET] \
-X POST https://api.razorpay.com/v1/payment_links/ \
-H 'Content-type: application/json' \
-d '{
"amount": 1000,
"currency": "INR",
"accept_partial": true,
"first_min_partial_amount": 100,
"reference_id": "#523442",
"description": "Payment for policy no #23456",
"customer": {
"name": "Gaurav Kumar",
"contact": "+919999999999",
"email": "gaurav.kumar#example.com"
},
"notify": {
"sms": true,
"email": true
},
"reminder_enable": true,
"options": {
"checkout": {
"method": {
//here you have to specify
"netbanking": "1",
"card": "1",
"upi": "0",
"wallet": "0"
}
}
}
}'
Edit
official docs: https://razorpay.com/docs/payments/payment-methods/

PayPal Sandbox approval URL stuck in infinite loop

I've got a strange issue with PayPal's Sandbox / API V2.
After creating an order with the AUTHORIZE intent (pre-auth). I'm taking the user to the APPROVE URL, and after selecting the payment method PayPal says that it's redirecting me back to my redirect_url, but instead it just reloads the payment selection screen.
I don't know what's wrong.... This is what I'm passing directly to the API:
curl -v -X POST https://api.sandbox.paypal.com/v2/checkout/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <my-access-token>" \
-d '{
"intent":"AUTHORIZE",
"description":"Description goes here",
"soft_descriptor":"Descriptor",
"purchase_units":[
{
"amount":{
"currency_code":"CAD",
"value":"351.75"
}
}
],
"order_application_context":{
"return_url":"redacted_for_privacy",
"cancel_url":"redacted_for_privacy"
}
}
That call is obviously working as PayPal is returning the CREATED response. I have looped through the returned HATEOAS links and redirected the user to the approve URL ... Then the problem starts...
API response is:
{
"id": "8KF74291SN313461D",
"intent": "AUTHORIZE",
"status": "CREATED",
"purchase_units": [
{
"reference_id": "default",
"amount": {
"currency_code": "CAD",
"value": "351.75"
},
"payee": {
"email_address": "sb-iuaiy3198427#business.example.com",
"merchant_id": "DXYXG2JAU3SQQ"
}
}
],
"create_time": "2020-09-15T05:13:59Z",
"links": [
{
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/8KF74291SN313461D",
"rel": "self",
"method": "GET"
},
{
"href": "https://www.sandbox.paypal.com/checkoutnow?token=8KF74291SN313461D",
"rel": "approve",
"method": "GET"
},
{
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/8KF74291SN313461D",
"rel": "update",
"method": "PATCH"
},
{
"href": "https://api.sandbox.paypal.com/v2/checkout/orders/8KF74291SN313461D/authorize",
"rel": "authorize",
"method": "POST"
}
]
}
Issue was their confusing API documentation.
order_application_context should be changed to: application_context in the API Call

NetSuite Rest API to get An Items Price

I am trying to use postman to get item price / price matrix. I can get item price levels if i perform a get request to: https://{{accountid}}.suitetalk.api.netsuite.com/services/rest/record/v1/itemgroup/{{item_number}}?expandSubResources=true
But it won't provide the item prices for each level, only the name of the levels. strangely, I won't even get the price level information if i send a similar request to other product types (in my case discount and non inventory item). Does anyone one know how i can extract product pricing information from netsuite. I have tried going through the Docs but it came up with nothing.
Here is the cURL of the request made to noninventoryitems module
curl --location --request GET 'https://5195388-sb1.suitetalk.api.netsuite.com/services/rest/record/v1/noninventoryitem/284/' \
--header 'Authorization: Bearer {{{accesstoken}}}"' \
--header 'Cookie: NS_ROUTING_VERSION=LAGGING'
You can execute a SuiteQL query.
POST https://{{accountid}}.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql
Header: Prefer: transient
Body:
{
"q": "SELECT i.item, i.pricelevelname, i.price, c.name as currency FROM itemprice i, currency c WHERE i.currencypage = c.id and item=967"
}
Sample output:
{
"links": [
{
"rel": "self",
"href": "https://[accountid].suitetalk.api.netsuite.com/services/rest/query/v1/suiteql?limit=1000&offset=0"
}
],
"count": 2,
"hasMore": false,
"items": [
{
"links": [],
"currency": "USD",
"item": "967",
"price": "100000",
"pricelevelname": "Base Price"
},
{
"links": [],
"currency": "USD",
"item": "967",
"price": "100000",
"pricelevelname": "Partner Pricing"
}
],
"offset": 0,
"totalResults": 2
}
The record and field IDs are in the Analytics Browser: https://[accountid].app.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2020_1/analytics/record/itemPrice.html.

FIWARE Orion: return subscription id

When creating a subscription, it would be nice to return the subscription ID.
For instance, the following code doesn't return anything :
curl localhost:1026/v2/subscriptions -s -S --header 'Content-Type: application/json' \
-d #- <<EOF
{
"description": "A subscription to get info about Room1",
"subject": {
"entities": [
{
"id": "Room1",
"type": "Room"
}
],
"condition": {
"attrs": [
"pressure"
]
}
},
"notification": {
"http": {
"url": "http://localhost:1028/accumulate"
},
"attrs": [
"temperature"
]
},
"expires": "2040-01-01T14:00:00.00Z",
"throttling": 5
}
EOF
In the subscription case, the resource id is generated server-side (with difference to the entities endpoint, where the id is decided client-side).
It would be nice to return it in the POST call, is there any way to do this?
Subscription ID is retrieved in Location header in the response to the subscription creation request, eg:
Location: /v2/subscriptions/5b991dfa12f473cee6651a1a
More details in the NGSIv2 API specification (check "Create Subscription" section).

Orion notification complex payload

I'm trying to use Orion notification to send SMS with Plivo.
This is how I send an SMS directly with Plivo:
curl -X POST https://api.plivo.com/v1/Account/MAMDA5ZDJIMDM1/Message/ -L -u MAMDA5ZDJIM:YzhiNDJjODNhNDkxMjhiYTgxZD -H 'Content-Type: application/json' -d #- <<EOF
{
"src": "0039414141414",
"dst": "0039414747111",
"text": "test SMS"
}
EOF
How should I encode it in Orion? I tried:
curl localhost:1026/v2/subscriptions -s -S --header 'Content-Type: application/json' --header 'Accept: application/json' -d #- <<EOF
{
"description": "A subscription to get info about WS_UPPA_Sensor2",
"subject": {
"entities": [
{
"id": "Sensor1",
"type": "SensingDevice"
}
],
"condition": {
"attrs": [
"temperature"
]
}
},
"notification": {
"httpCustom": {
"url": "https://api.plivo.com/v1/Account/MAMDA5ZDJIMDM1NZVMZD/Message/",
"headers": {
"Authorization": "Basic TUFNREE1WkRKSU1ETTFOWlZNWkQ6WXpoaU5ESmpPRE5oTkRreE1qaGlZVGd4WkRkaE5qYzNPV1ZsTnpZMA=="
},
"payload": "{%22src%22%3A%2200393806412092%22%2C%22dst%22%3A%2200393806412093%22%2C%22text%22%3A%22test%20SMS%20from%20Waziup%22}"
},
"attrs": [
"temperature"
]
},
"expires": "2040-01-01T14:00:00.00Z",
"throttling": 5
}
EOF
Is there another way than percent encoding?
URL encoding (I understand is the one you refer by "percent encoding") is the only one which have an special treatment in custom notifications (details described as part of the Orion documentation).
In fact, taking into account the existing one is complete (I mean, any text can be expressed in the terms of URL encoding) there is no need of adding any other.