Reputation: 21
I am new to PayPal and I am trying to create an app like Fiverr and Upwork where users can sell services and get paid but before they start to sell services they need to connect their PayPal accounts so when they sell their service they get paid and we take 5% of the amount and this process of getting paid is automatic so the money goes directly into their PayPal account
here is my code and I can connect the user successfully to my app I get the merchant id and everything but when I try to transfer payment to them i get the error
i am using laravel 9 with srmklive/paypal package
my Button Code
<a href="{{ route('paypal.connect')}}">
<x-jet-secondary-button>Connect Your Paypal</x-jet-secondary-button>
</a>
<a href="{{ route('paypal.process' , ['order_no' => 'Ord62399de81ab99']) }}">
<x-jet-secondary-button>Pay with your Paypal</x-jet-secondary-button>
</a>
My routes
Route::get('/process/{order_no}', [PaypalController::class, 'processPaypal'])->name('process');
Route::get('/success', [PaypalController::class, 'processSuccess'])->name('success');
Route::get('/cancel', [PaypalController::class, 'processCancel'])->name('cancel');
Route::get('/connect', [PaypalController::class, 'connect'])->name('connect');
Route::get('/connect/success', [PaypalController::class, 'connectSuccess'])->name('connect.success');
My controller Code Right now for testing, I have one buyer and one seller so when I pay only this seller will get paid for now, so that why i have passed there marchent_id statically and once I have implemented this successfully I will add it to the database in the user table so every user will have their merchant id <?php
namespace App\Http\Controllers;
use App\Models\Order;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Srmklive\PayPal\Services\PayPal as PayPalClient;
class PaypalController extends Controller
{
public $provider;
public function __construct()
{
$this->provider = new PayPalClient;
$this->provider->setApiCredentials(config('paypal'));
$this->provider->setRequestHeader('PayPal-Partner-Attribution-Id', '<BN_CODE>');
// $this->provider->setReturnAndCancelUrl(route('dashboard'), route('dashboard'));
$paypalToken = $this->provider->getAccessToken();
}
public function connect()
{
$provider = new PayPalClient;
$provider->setApiCredentials(config('paypal'));
$paypalToken = $provider->getAccessToken();
$provider->setAccessToken($paypalToken);
$res = $provider->createPartnerReferral([
"tracking_id" => uniqid(Str::random(40), true),
"partner_config_override" => [
"return_url" => route('paypal.connect.success')
],
"operations" => [
[
"operation" => "API_INTEGRATION",
"api_integration_preference" => [
"rest_api_integration" => [
"integration_method" => "PAYPAL",
"integration_type" => "FIRST_PARTY",
"first_party_details" => [
"features" => [
"PAYMENT",
"REFUND"
],
]
]
]
]
],
"products" => [
"EXPRESS_CHECKOUT"
],
"legal_consents" => [
[
"type" => "SHARE_DATA_CONSENT",
"granted" => true
]
]
]);
//action_url
if (isset($res['links'])) {
foreach ($res['links'] as $link) {
if ($link['rel'] == 'action_url') {
return redirect()->away($link['href']);
}
}
return redirect()->route('dashboard')->with('something went wrong');
}
}
public function connectSuccess(Request $request)
{
if (isset($request['merchantId']) &&
$request['merchantId'] != null &&
$request['permissionsGranted'] === true &&
$request['isEmailConfirmed'] === true) {
redirect()->to(env('APP_URL') . "/dashboard?merchantId=" . $request['merchantId'] . "&merchantIdInPayPal=" . $request['merchantIdInPayPal'] . "&permissionsGranted=true&accountStatus=BUSINESS_ACCOUNT&consentStatus=true&productIntentId=addipmt&isEmailConfirmed=true&returnMessage=To%20start%20accepting%20payments,%20please%20log%20in%20to%20PayPal%20and%20finish%20signing%20up")
->with('success', 'your account is Linked Successfully');
} else {
redirect()->route('dashboard')->with('error', $request['massage']);
}
}
public function processPaypal(Request $request)
{
// $response = $this->provider->createOrder([
// "intent" => "CAPTURE",
// "application_context" => [
// "return_url" => route('paypal.success'),
// "cancel_url" => route('paypal.cancel'),
// ],
// "purchase_units" => [
// 0 => [
// "amount" => [
// "currency_code" => "USD",
// "value" => "1.00"
// ]
// ]
// ]
// ]);
$order = Order::with('freelancer')->where('order_no', $request->order_no)->first();
$response = $this->provider->createOrder([
"headers" => "PayPal-Partner-Attribution-Id: <FLAVORsb-u4l7k14614776_MP>",
"intent" => "CAPTURE",
"application_context" => [
"return_url" => route('paypal.success'),
"cancel_url" => route('paypal.cancel'),
],
"purchase_units" => [
0 => [
"amount" => [
"currency_code" => "USD",
"value" => "5.00"
],
"payee" => [
"merchant_id" => "7PYAZ7V939UJW"
],
"payment_instruction" => [
"disbursement_mode" => "INSTANT",
"platform_fees" => [
0 => [
"amount" => [
"currency_code" => "USD",
"value" => "1.00"
],
"payee" => [
"merchant_id" => env("MY_PAYPAL_MARCHENT_ID")
]
]
]
]
],
]
]);
if (isset($response['id']) && $response['id'] != null) {
// redirect to approve href
foreach ($response['links'] as $links) {
if ($links['rel'] == 'approve') {
return redirect()->away($links['href']);
}
}
return redirect()
->route('orders.index')
->with('error', 'Something went wrong.');
} else {
return redirect()
->route('orders.index')
->with('error', $response['message'] ?? 'Something went wrong.');
}
}
public function processSuccess(Request $request)
{
$response = $this->provider->capturePaymentOrder($request['token']);
if (isset($response['status']) && $response['status'] == 'COMPLETED') {
return redirect()
->route('dashboard')
->with('success', 'Transaction complete.');
} else {
return redirect()
->route('dashboard')
->with('error', $response['message'] ?? 'Something went wrong.');
}
}
public
function processCancel(Request $request)
{
return redirect()
->route('orders.index')
->with('error', $response['message'] ?? 'You have canceled the transaction.');
}
}
Here is the error I get when I try to transfer the money
{} {"name":"NOT_AUTHORIZED","details":[{"issue":"PAYEE_NOT_CONSENTED","description":"Payee does not have appropriate consent to allow the API caller to process this type of transaction on their behalf. Your current setup requires the 'payee' to provide a consent before this transaction can be processed successfully."}],"message":"Authorization failed due to insufficient permissions.","debug_id":"3f2c4f80f412c","links":[{"href":"https://developer.paypal.com/docs/api/orders/v2/#error-PAYEE_NOT_CONSENTED","rel":"information_link","method":"GET"}]}
Upvotes: 0
Views: 339
Reputation: 1304
about the error, it mean that you didnt have permission to create order on behalf of the payee 7PYAZ7V939UJW
I see you are using a static
"payee" => [
"merchant_id" => "7PYAZ7V939UJW"
]`;
this means that the payee at all orders will be this mentioned id, but you need to make this dynamic,
you need to update your code logic,
at the connectSuccess
method, need to keep the connected account data merchant_id
and attach them to the seller data in your DB, to use them at creating orders related to the connected seller.
also, it will be better to move the platform payee merchant_id
to .env instead writing it statically.
Upvotes: 1