Seller PayPal account not receiving payment on REST API payment - paypal

I'm trying to implement server side paypal rest api in django rest framework,i have to say paypal's documentation is not helping matters at all,but so far i have been able to successfully pay money from a sandbox buyer account by first getting access token:
def generate_access_token():
url="https://api-m.sandbox.paypal.com/v1/oauth2/token"
headers={
'Content-Type': 'application/json'
}
auth=(settings.PAYPAL_CLIENT_ID,settings.PAYPAL_SECRET_KEY)
data={
"grant_type":"client_credentials"
}
response=requests.post(url,headers=headers,auth=auth,data=data)
token=response.json()['access_token']
return token
Then i create an order for the buyer to pay:
def pay_for_order(token,price,order_id):
url="https://api-m.sandbox.paypal.com/v2/checkout/orders"
headers={
'Content-Type': 'application/json',
'Authorization':f'Bearer {token}'
}
data={
'intent':'CAPTURE',
'application_context':{
'return_url':f'http://127.0.0.1:8000/payment/confirm-payment/1/{token}/',
'cancel_url':f'http://127.0.0.1:8000/payment/confirm-payment/2/{token}/'
},
'purchase_units':[
{
"reference_id":f'{order_id}',
"amount":{
'currency_code':'USD',
'value':f'{price}'
}
}
]
}
response=requests.post(url,headers=headers,data=json.dumps(data))
print(response.json())
response_json=response.json()
return response_json
then the order capture is called in the endpoint in the return url when payment is successful like this:
def final_payment_verification(token,paypal_token):
url=f'https://api.sandbox.paypal.com/v2/checkout/orders/{paypal_token}/capture'
headers={
'Content-Type': 'application/json',
'Authorization':f'Bearer {token}'
}
response=requests.post(url,headers=headers)
print(response.json())
response_json=response.json()
return response_json
but the major issue now is that the seller doesn't get credited my intuition was that generating access token with seller's client id and secret key already stands as identification for whoever the buyer's payment is going to but unfortunately only the buyer get's debited,i checked the whole order api on paypal docs but couldn't find fields that require buyers or recipient info so paypal can pay to them,all solutions online are for client side checkout and paypal docs are not helping matters at all,there are even some read more pages that lead to totally diffrent unrelated content and every resource online mostly use the v1 version other than the latest v2,I would really like to know what i'm doing wrong.

The code is in sandbox mode, so you must be using a sandbox client ID and secret. Are you looking in the seller sandbox account (open a separate tab to log in to www.sandbox.paypal.com with it) that corresponds to the REST APP client ID and secret you are using?
If you still have issues, log the entire capture API response body and include it in your question.

Related

Paypal - "ID token context does not have required scope" error when trying to render paypal button using saved payment info

I have been trying to save customer payment details on a site, so that if a customer is logged in they can pay with a single click, instead of having to log in to paypal. To do so I have been following the official paypal guide: https://developer.paypal.com/beta/vault/during-purchase/js-sdk/paypal/
I was able to successfully save payment details. The problem is that when I try to use the saved customer_id to use those saved payment details, I get the following error: "Error: cannot get vault - ID token context does not have required scope".
What I did was the following:
Generate an id_token and access_token by sending a request to https://api-m.sandbox.paypal.com/v1/oauth2/token and specifying response_type=id_token
When rendering the paypal button, pass the generated id_token to the script tags data-user-id-token attribute.
I click the paypal button on the website. This sends a request to my backend server which generates an order by sending a request to https://api-m.sandbox.paypal.com/v2/checkout/orders/. When generating the order I use the generated access_token as a Bearer token in the "Authorization" header, as well as pass the following payment_source.paypal configuration:
"paypal": {
"attributes": {
"vault": {
"store_in_vault": "ON_SUCCESS",
"usage_type": "MERCHANT",
"customer_type": "CONSUMER"
}
}
I get an order id in the response. I pass this order id back to the client side, where the paypal sdk initates a payment flow using this id.
I finish the payment flow, and on success call my server's captureOrder endpoint. This calls https://api-m.sandbox.paypal.com/v2/checkout/orders/$id/capture, where $id is the orderID used before. I also pass the Beares access_token generated in the first step. This request returns a response containing a generated user ID that looks something like this: 560837847
I send another request to https://api-m.sandbox.paypal.com/v1/oauth2/token, this time passing a target_customer_id parameter in the request's body. The value of the parameter is the customerId generated in the 5th step.
I render the page with the paypal button again, this time passing the new id_token to the script tags data-user-id-token attribute.
The error "Error: cannot get vault - ID token context does not have required scope" appears in the developer tools console.
I have turned on "Accept payments" on the Paypal developer console as well as Vault functionality:
The id_token generated in the 6th step has the following scopes:
https://uri.paypal.com/services/invoicing
https://uri.paypal.com/services/vault/payment-tokens/read
https://uri.paypal.com/services/disputes/read-buyer
https://uri.paypal.com/services/payments/realtimepayment
https://uri.paypal.com/services/disputes/update-seller
openid
https://uri.paypal.com/services/payments/payment/authcapture
https://uri.paypal.com/services/disputes/read-seller
Braintree:Vault
https://uri.paypal.com/services/payments/refund
https://api.paypal.com/v1/vault/credit-card
https://api.paypal.com/v1/payments/.*
https://uri.paypal.com/payments/payouts
https://uri.paypal.com/services/vault/payment-tokens/readwrite
https://api.paypal.com/v1/vault/credit-card/.*
https://uri.paypal.com/services/shipping/trackers/readwrite
https://uri.paypal.com/services/subscriptions
https://uri.paypal.com/services/applications/webhooks
I cannot find any information online about what else I should do to make this work.

How to void an authorization from PayPal for a third party merchant

I'm trying to run a void action on an transaction with the intent of authorize for a third party merchant
import paypal from "#paypal/checkout-server-sdk";
...
const req = new paypal.payments.AuthorizationsVoidRequest(id);
const voidRequest = await client.execute(req);
const refundId = voidRequest.headers['paypal-debug-id'];
but i'm getting an error Authorization failed due to insufficient permissions. You do not have permission to access or perform operations on this resource.
according to this link I need to get extra permission from the merchant
Note:For three party transactions in which a partner is managing the API calls on behalf of a merchant, the partner must identify the merchant using either a PayPal-Auth-Assertion header or an access token with target_subject.
how do I get those permissios from the merchant? do I need to add a connect with paypal button for my merchants? is there even such a thing?
or I just need to add PayPal-Auth-Assertion (not sure how to do that as well, how do i get the merchant access_token/client_id ?
...
req.headers['PayPal-Auth-Assertion'] = generateAuthAssertionHeader("XXXX#XXXX.com");
...
const generateAuthAssertionHeader = async email => {
const auth_1 = Buffer.from('{"alg":"none"}').toString('base64');
const auth_2 = Buffer.from(`{"email":"${email}","iss":"${PAYPAL_CLIENT_ID}"}`).toString('base64'); //my PAYPAL_CLIENT_ID or my merchant? how can I get the merchant PAYPAYL_CLIENT_ID
const auth_assertion_header = `${auth_1}.${auth_2}.`;
return auth_assertion_header;
};
Your link links to https://developer.paypal.com/api/rest/requests/#paypal-auth-assertion which explains the header. Consent can be gotten with Connect/Log in with PayPal, if your application is approved for that scope by PayPal
Otherwise, ask the merchant for their own REST APP client id and secret when they are onboarded to your system, and use those credentials to void as a first party.

Using Stripe API with Flutter Dio package Flutter to Add Cards, Payment Methods, Accounts

Noobish Dev here. I'm developing an app that involves processing payments between customers and a particular service, the app would take a fee and pay the service provider directly to their bank accounts. Looking for advice really or perhaps a better implementation.
Anyway, after watching some tutorials online I developed the app to use my own form to handle a customers card data and send directly to Stripes API with curl request. In this instance to attach the card to a customer account. I find that stripe requires the apps/websites be PCI compliant when handling data and to not use custom form handling for fear of retaining card data, that leaves me stuck as this particular method we use by directly interacting with the API (I'm using Dio) is not recommended by Stripe as advised below.
App screenshot :
The snippet of code (works fine by the way):
Future<void> addCard(
{int cardNumber,
int month,
int year,
int cvc,
String stripeId,
String userId,
String cardHolderName,
String email}) async {
Map body = {
"type": "card",
"card[number]": cardNumber,
"card[exp_month]": month,
"card[exp_year]": year,
"card[cvc]": cvc,
"billing_details[name]": cardHolderName,
"billing_details[email]": email
};
dynamic stripeResponse;
try {
print('Successfully added payment method id $paymentMethodUrl');
Dio dio = Dio();
await dio
.post(paymentMethodUrl,
data: body,
options: Options(
contentType: Headers.formUrlEncodedContentType,
headers: headers))
.then((response) {
print(response.data);
stripeResponse = response;
String paymentId = response.data['id'];
Map stripeCustomer = {"customer": UserData.stripeID};
try {
dio
.post('$paymentMethodUrl/$paymentId/attach',
data: stripeCustomer,
options: Options(
contentType: Headers.formUrlEncodedContentType,
headers: headers))
.then((response) {
print(response.data);
print('Attached successfully');
});
} on DioError catch (e) {
print('Error attaching card to customer: ${e.response.data['error']['message']}');
}
});
} on DioError catch (e) {
print(stripeResponse);
print('Error adding card: ${e.response.data['error']['message']}');
}
}
https://stripe.com/docs/security#pci-dss-guidelines
The easiest way to be PCI compliant is as advised by Stripe:
Use one of our recommended payments integrations to collect payment information, which is securely transmitted directly to Stripe without it passing through your servers
Serve your payment pages securely using Transport Layer Security (TLS) so that they make use of HTTPS
Anyway I would appreciate it if anyone could give me some advice on this or maybe I'm misunderstanding something when it comes to compliance. I might just instead use Apple pay and Google pay if this option is not viable as I don't want to get into trouble if I'm not PCI compliant due to handing card data.
Thanks in advance.
As stated in thisSO post:
The sensitive information governed by PCI (i.e. raw card data) is sent
directly from the client to Stripe. Stripe creates a Payment Method to
represent that data (pm_) and returns that to the client so it can be
referenced from there.
However, Payment Intents must be created server-side in a secure
context with a secret or restricted API key, then the Payment Intent's
client secret should be sent to the client to allow for client-side
confirmation.
The section about validating your PCI compliance in Stripe's integration security guide has more information.
And as mentioned in the comment, you can explore using the plugins to provide all the functions you need for your app. I suggest to look into this flutter_stripe which was published by flutterstripe.io. You can also check out this blog(https://flutterstripe.medium.com/announcing-the-flutter-sdk-for-stripe-1ba2b3ee667c) where it was mentioned about the security feature that the package could offer:
Secure by default
SCA-Ready: The SDK automatically performs native 3D Secure authentication if needed
to comply with Strong Customer
Authentication
regulation in Europe.
PCI compliant: as the plugin does not handle sensitive information (such as credit card credentials) the plugin is PCI
compliant by default. You can find out more about PCI compliance and
why it’s important here.

Venmo API returns undocumented error 1396 on payment endpoint

The error looks something like this
request.post({
url: 'https://api.venmo.com/v1/payments',
form: {
access_token: 'xxxxxxxxxxxxxxxxxxxxxx',
email: req.body.email,
note: 'Payment of ' + req.user.coins + ' coins',
amount: (req.user.coins * coin_price),
audience: 'public',
confirm: true
}
}, function(err, httpResponse, body) {
console.log(err, body)
} )
and the json response looks like this
{"error": {"message": "Please confirm whether you would like to pay a fee on this transaction", "code": 1396}}
I feel this is because on my account I have a credit card that requires a 3% fee. But I am fine with it. Is there a way I can auto accept this?
The documentation is here: Venmo payments
I work at Braintree, same company as Venmo. If you have more questions, you can always reach out to the Venmo support team.
That error occurs when you don't have a default funding source set, and the only funding source available is your credit card. Setting any default funding source (card or otherwise) will fix the problem. Its purpose is to prevent you accidentally incurring fees.
Thanks for reporting the undocumented error, we'll add it. We'll also update the error message to be more clear.

PayPal REST API 500 internal service error only in live

I am using the Paypal PHP REST API SDK, but I can reproduce the problem using curl too. I am able to get a token without a problem. This only occurs when I'm submitting a live payment. I can switch to sandbox and submit an identical payment successfully.
As you can see below this is a very basic payment. I don't see how there could possibly be a problem with the information being submitted.
I have no shortage of debug IDs since this happens every time, but here is the last one I got: 049eee254433f
{
"intent":"sale",
"payer":{
"payment_method":"credit_card",
"funding_instruments":[
{
"credit_card":{
"type":"visa",
"number":"(removed)",
"cvv2":"(removed)",
"expire_month":"1",
"expire_year":"2016",
"first_name":"(removed)",
"last_name":"(removed)"
}
}
]
},
"transactions":[
{
"amount":{
"total":"11.98",
"currency":"USD"
}
}
]
}
The issue, according to the debug ID, is that you are not sending the billing address along with the card information. The option to include/not include the billing address with your request is based upon your merchant account setup. In order to rectify the above error, please provide the billing address in your request.
https://developer.paypal.com/webapps/developer/docs/api/#creditcard-object