问题
I'm trying to implement the API of PayPal payment with Laravel 5.1. But when I log in to PayPal (sandbox), it uses the address I used in my account, and also it uses the name from PayPal account not the data from my website. That's my problem.
I want to use the data from my website because it doesn't make sense if I enter the shipping address (for example) from my website and not using it. Please see my code below for reference (Or comment down below for some details from me).
class PaypalPaymentController extends BaseController
{
private $_api_context;
public function __construct(){
$paypal_conf = \Config::get('paypal');
$this->_api_context = new ApiContext(new OAuthTokenCredential(
$paypal_conf['client_id'],
$paypal_conf['secret']
));
$this->_api_context->setConfig($paypal_conf['settings']);
}
public function payWithPaypal(Request $request){
$payer = new Payer;
$payer->setPaymentMethod('paypal');
$price = 0;
switch($request->get('amount')) {
case '10 books':
$price = 6200;
break;
case '20 books':
$price = 12200;
break;
case '50 books':
$price = 25200;
break;
default:
return redirect()
->route('bookstore.shipping')
->with('danger', 'Please select the right amount of book/s.');
break;
}
$item1 = new Item();
$item1->setName($request->get('amount'))
->setCurrency('PHP')
->setQuantity(1)
->setPrice($price);
$item_list = new ItemList();
$item_list->setItems([$item1]);
$amount = new Amount();
$amount->setCurrency('PHP')
->setTotal($price);
$transaction = new Transaction();
$transaction->setAmount($amount)
->setItemList($item_list)
->setDescription('Books transaction');
$redirect_urls = new RedirectUrls();
$redirect_urls->setReturnUrl(route('bookstore.payment-status'))
->setCancelUrl(route('bookstore.payment-status'));
$payment = new Payment();
$payment->setIntent('Sale')
->setPayer($payer)
->setRedirectUrls($redirect_urls)
->setTransactions([$transaction]);
$patchReplace = new Patch();
$patchReplace->setOp('add')
->setPath('/transactions/0/item_list/shipping_address')
->setValue(json_decode('{
"line1": "345 Lark Ave",
"city": "Montreal",
"state": "QC",
"postal_code": "H1A4K2",
"country_code": "CA"
}'));
$patchRequest = (new PatchRequest())->setPatches([$patchReplace]);
try{
$payment->create($this->_api_context);
$payment->update($patchRequest, $this->_api_context);
} catch(\Palpal\Exception\PPConnectionException $e){
if(\Config::get('app.debug')){
return redirect()
->route('bookstore.shipping')
->with('danger', 'Connection Timeout.');
}
return redirect()
->route('bookstore.shipping')
->with('danger', 'Some error occured, sorry for the inconvenience.');
}
foreach($payment->getLinks() as $link){
if($link->getRel() == 'approval_url'){
$redirect_url = $link->getHref();
break;
}
}
Session::put('paypal_payment_id', $payment->getId());
if(isset($redirect_url)){
return Redirect::away($redirect_url);
}
return redirect()
->route('bookstore.shipping')
->with('danger', 'Unknown error occured.');
}
public function getPaymentStatus(){
$payment_id = Session::get('paypal_payment_id');
Session::forget('paypal_payment_id');
if(empty(Input::get('PayerID')) || empty(Input::get('token'))){
return redirect()
->route('bookstore.shipping')
->with('danger', 'Payment failed.');
}
$payment = Payment::get($payment_id, $this->_api_context);
$execution = new PaymentExecution();
$execution->setPayerId(Input::get('PayerID'));
$result = $payment->execute($execution, $this->_api_context);
if($result->getState() == 'approved'){
// Send Email
$email_data = [
'number_of_books' => $payment->transactions[0]->item_list->items[0]->name,
'shipping' => [
'street' => $payment->payer->payer_info->shipping_address->line1,
'city' => $payment->payer->payer_info->shipping_address->city,
'state' => $payment->payer->payer_info->shipping_address->state,
'country' => $payment->payer->payer_info->shipping_address->country_code,
]
];
// Send email function here ...
return redirect()
->route('bookstore.shipping')
->with('success', 'Transaction payment success!');
}
return redirect()
->route('bookstore.shipping')
->with('danger', 'Payment failed.');
}
}
I also reviewed this link but it seems like it cannot answer my problem. Also, what if the country has a province? How can we add that?
Update 1
- Added new
Patch()class. - Edited Code in
Try Catch.
Note: The accepted answer will also receive the bounty plus the up.
Update 2 with Tutorial
For PHP/Laravel (I'm currently using v5.1), install this package paypal/rest-api-sdk-php
Create Sandbox account in PayPal. Choose Buy with Paypal.
Continue until you see options, choose Shop the world.
Login to developer.paypal.com.
Click Accounts. Click Create Account.
Choose what country you want. Choose Personal (Buyer Account) in Account Type.
Add email address, avoid to use
-. Use_instead.Enter how much PayPal Balance you want.
Click Create Account.
Make it live?
https://github.com/paypal/PayPal-PHP-SDK/wiki/Going-Live
回答1:
After you have created the payment, try updating the address as shown in this example.
$paymentId = $createdPayment->getId();
$patch = new \PayPal\Api\Patch();
$patch->setOp('add')
->setPath('/transactions/0/item_list/shipping_address')
->setValue([
"recipient_name" => "Gruneberg, Anna",
"line1" => "52 N Main St",
"city" => "San Jose",
"state" => "CA",
"postal_code" => "95112",
"country_code" => "US"
]);
$patchRequest = new \PayPal\Api\PatchRequest();
$patchRequest->setPatches([$patch]);
$result = $createdPayment->update($patchRequest, $apiContext);
I also reviewed this link but it seems like it cannot answer my problem. Also, what if the country has a province? How can we add that?
Use the state codes listed here.
回答2:
I have not used the PayPal API in a long while, but just skimming over the docs shows that the payer_info shipping address field is deprecated (https://developer.paypal.com/docs/api/orders/v1/#definition-payer_info) and suggests to use the shipping address in the purchase_unit instead.
According to the Docs, this should be set in the CartBase class with the setItemList() function (http://paypal.github.io/PayPal-PHP-SDK/docs/class-PayPal.Api.CartBase.html).
Edit:
So, for the package you are using, you'll need to add the PayPal\Api\ShippingAddress object to your $item_list variable:
$shipping = new PayPal\Api\ShippingAddress();
$shipping->setLine1('123 1st St.')
->setCity('Some City')
->setState('CA')
->setPostalCode("95123")
->setCountryCode("US")
->setPhone("555-555-5555")
->setRecipientName("John Doe");
$item_list = new ItemList();
$item_list->setItems([$item1])
->setShippingAddress($shipping);
ItemList class ref: http://paypal.github.io/PayPal-PHP-SDK/docs/source-class-PayPal.Api.ItemList.html#74-85
回答3:
I think this is the relevant documentation you are looking for.
For people who already have PayPal accounts and whom you already prompted for a shipping address before they choose to pay with PayPal, you can use the entered address instead of the address the person has stored with PayPal.
Instead of using the address saved in their account,
The payer is shown the passed-in address but cannot edit it. No address is shown if the address is invalid, such as missing required fields like country, or if the address is not included at all.
Edit: Try something like this in place of what you have.
$address = new ShippingAddress();
$address->setCity('Toronto');
$address->setState('ON');
$address->setCountryCode('CA');
$address->setLine1('123 Fake Street');
$address->setPostalCode('M1M1M1');
$payerInfo = new PayerInfo();
$payerInfo->setShippingAddress($address);
$payer = new Payer();
$payer->setPaymentMethod('paypal');
回答4:
I haven't worked with PayPal very much, but I'm taking this from the official documentation, so I'm confident it will work for you. Overriding addresses stored with PayPal. For a list of available variables you can use in the checkout page, see Auto-fill PayPal checkout page variables.
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<!-- Enable override of buyers's address stored with PayPal . -->
<input type="hidden" name="address_override" value="1">
<!-- Set variables that override the address stored with PayPal. -->
<input type="hidden" name="first_name" value="John">
<input type="hidden" name="last_name" value="Doe">
<input type="hidden" name="address1" value="345 Lark Ave">
<input type="hidden" name="city" value="Montreal">
<input type="hidden" name="state" value="QC">
<input type="hidden" name="zip" value="H1A4K2">
<input type="hidden" name="country" value="CA">
<input type="image" name="submit"
src="https://www.paypalobjects.com/en_US/i/btn/btn_buynow_LG.gif"
alt="PayPal - The safer, easier way to pay online">
</form>
Or, from inside your script...
$address = new ShippingAddress();
$address->setCity('Montreal');
$address->setState('QC');
$address->setCountryCode('CA');
$address->setLine1('345 Lark Ave');
$address->setPostalCode('H1A4K2');
$payerInfo = new PayerInfo();
$payerInfo->setShippingAddress($address);
Here's the list of available province codes. You would use these two-letter strings for the "state" variable, just like you would a U.S. state. PayPal State and Province codes
Province name | Province code
Alberta |
ABBritish Columbia |
BCManitoba |
MBNew Brunswick |
NBNewfoundland and Labrador |
NLNorthwest Territories |
NTNova Scotia |
NSNunavut |
NUOntario |
ONPrince Edward Island |
PEQuebec |
QCSaskatchewan |
SKYukon |
YT
I hope this helps you.
来源:https://stackoverflow.com/questions/51130271/paypal-api-with-laravel-updating-of-data