Reputation: 161
I have an issue dealing with the PayPal-PHP-SDK SDK found here: https://github.com/paypal/PayPal-PHP-SDK/
I have set it up, and everything sends to PayPal, and returns to me successfully, however the status set to both the billing agreement, and the response to my servers shows the status as pending.
Here is the controller (I'm using Laravel, if it helps. I chose not to use the modules as it seemed to be more difficult to use than the API with subscriptions)
$apiContext = new ApiContext(new OAuthTokenCredential('no probs here', 'no probs here'));
if(Input::get('package') == 'basic'){
$name = 'Basic';
$price = 5;
$pid = 1;
}
elseif(Input::get('package') == 'pro'){
$name = 'Pro';
$price = 10;
$pid = 2;
}
elseif(Input::get('package') == 'enterprise'){
$name = 'Enterprise';
$price = 15;
$pid = 3;
}
$payer = new Payer();
$payer->setPaymentMethod('paypal');
$billing = [];
$billing['name'] = 'One Month of a '.$name;
$billing['type'] = 'Regular';
$billing['frequency'] = 'MONTH';
$billing['frequency_interval'] = '1';
$billing['amount'] = [];
$billing['amount']['currency'] = 'USD';
$billing['amount']['value'] = $price.'.00';
$billing['cycles'] = '0';
$originalpayment = [];
$originalpayment['amount'] = [];
$originalpayment['amount']['currency'] = 'USD';
$originalpayment['amount']['value'] = $price.'.00';
$merchantPreferences = new MerchantPreferences();
$merchantPreferences->setReturnUrl("http://clan.rocks/api/pay/return/paypal")->setCancelUrl("http://clan.rocks/api/pay/cancel/paypal")->setInitialFailAmountAction('CANCEL')->setSetupFee($originalpayment['amount']);
$plan = new Plan();
$plan->setName($name.' -- Subscription')->setDescription('Monthly Subscription to a '.$plan.' on.')->setType('infinite')->setPaymentDefinitions(array($billing))->setMerchantPreferences($merchantPreferences);
try {
$planres = $plan->create($apiContext);
} catch (Exception $ex) {
dd('PLAN ERROR: '.trim($ex,9000));
exit(1);
}
try {
$patch = new Patch();
$value = new PPModel('{
"state":"ACTIVE"
}');
$patch->setOp('replace')
->setPath('/')
->setValue($value);
$patchRequest = new PatchRequest();
$patchRequest->addPatch($patch);
$planres->update($patchRequest, $apiContext);
$finalplan = Plan::get($planres->getId(), $apiContext);
} catch (Exception $ex) {
dd(trim($ex,9000));
exit(1);
}
$payer = [];
//todo: input
$payer['payment_method'] = 'paypal';
$now = Carbon::now()->addMonth();
$plantime = $now->toIso8601String();
$newdate = (string)str_replace('+0000','Z',$plantime);
$planner = [];
$planner['id'] = $finalplan->getID();
$agreement = new Agreement();
$agreement->setName(''.$name)
->setDescription($name.' on Subscription - $'.$price.'.00')
->setStartDate($newdate)
->setPlan($planner)
->setPayer($payer);
// ### Create Agreement
try {
// Please note that as the agreement has not yet activated, we wont be receiving the ID just yet.
$agreement = $agreement->create($apiContext);
// ### Get redirect url
// The API response provides the url that you must redirect
// the buyer to. Retrieve the url from the $agreement->getLinks()
// method
foreach ($agreement->getLinks() as $link) {
if ($link->getRel() == 'approval_url') {
$approvalUrl = $link->getHref();
break;
}
}
} catch (Exception $ex) {
dd('AGREEMENT ERROR:'.trim($ex,9000));
}
dd($agreement);
$tokensec = explode('token=', $approvalUrl);
$token = $tokensec[1];
$paycheck = new PPAuth;
$paycheck->uid = Auth::user()->id;
$paycheck->token = $token;
$paycheck->pid = $pid;
$paycheck->active = 0;
$paycheck->save();
if(isset($approvalUrl)) {
// redirect to paypal
return Redirect::away($approvalUrl);
}
return Redirect::to('/final/error');
}
if(Input::get('payment') == 'btc'){
dd('BTC Method not available atm');
}
}
public function paypalback(){
$apiContext = new ApiContext(new OAuthTokenCredential('no', 'no'));
// Get the payment ID before session clear
if (Request::segment(3) == 'return') {
$token = $_GET['token'];
$agreement = new \PayPal\Api\Agreement();
try {
$ff = $agreement->execute($token, $apiContext);
} catch (Exception $ex) {
dd(trim($ex,9000));
exit(1);
}
try {
$agreement = Agreement::get($agreement->getId(), $apiContext);
} catch (Exception $ex) {
dd(trim($ex,9000));
exit(1);
}
if($agreement->getState() == 'Pending' || $agreement->getState() == 'pending'){
dd('Payment pending. Please wait.......... RESULTS:'.$agreement);
}else{
dd($agreement);
}
if(!$token = PPAuth::where('token',$token)->first()){
dd("Payment successful. System Failure. Please contact support with key: ".$token);
}
if($token->pid == 1){
$product = 'basic';
}
elseif($token->pid == 2){
$product = 'pro';
}
elseif($token->pid == 3){
$product = 'enterprise';
}
$token->active = 1;
$token->save();
$genkey = new GenKey;
$genkey->uid = $token->uid;
$genkey->key = $product.'-'.md5($token).str_random(25);
$genkey->product = $product;
$genkey->pid = $token->pid;
$genkey->save();
return Redirect::to('/create/key/'.$genkey->key);
} else {
dd('ERROR');
}
Here is what is sent:
object(PayPal\Api\Agreement)#320 (1) { ["_propMap":"PayPal\Common\PPModel":private]=> array(6) { ["name"]=> string(21) "Basic" ["description"]=> string(45) "Basic on Subscription - $5.00" ["start_date"]=> string(20) "2014-12-07T21:23:56Z" ["plan"]=> object(PayPal\Api\Plan)#322 (1) { ["_propMap":"PayPal\Common\PPModel":private]=> array(7) { ["id"]=> string(26) "P-2AL73842PG948231ARQSGRMA" ["state"]=> string(6) "ACTIVE" ["name"]=> string(29) "Basic -- Subscription" ["description"]=> string(78) "Monthly Subscription to a {"name":"Basic -- Subscription"} on." ["type"]=> string(8) "INFINITE" ["payment_definitions"]=> array(1) { [0]=> object(PayPal\Api\PaymentDefinition)#325 (1) { ["_propMap":"PayPal\Common\PPModel":private]=> array(8) { ["id"]=> string(27) "PD-2YV51941E5203922VRQSGRMA" ["name"]=> string(28) "One Month of a Basic" ["type"]=> string(7) "REGULAR" ["frequency"]=> string(5) "Month" ["amount"]=> object(PayPal\Api\Currency)#326 (1) { ["_propMap":"PayPal\Common\PPModel":private]=> array(2) { ["currency"]=> string(3) "USD" ["value"]=> string(1) "5" } } ["cycles"]=> string(1) "0" ["charge_models"]=> object(PayPal\Api\ChargeModel)#323 (1) { ["_propMap":"PayPal\Common\PPModel":private]=> array(0) { } } ["frequency_interval"]=> string(1) "1" } } } ["merchant_preferences"]=> object(PayPal\Api\MerchantPreferences)#324 (1) { ["_propMap":"PayPal\Common\PPModel":private]=> array(6) { ["setup_fee"]=> object(PayPal\Api\Currency)#327 (1) { ["_propMap":"PayPal\Common\PPModel":private]=> array(2) { ["currency"]=> string(3) "USD" ["value"]=> string(1) "5" } } ["max_fail_attempts"]=> string(1) "0" ["return_url"]=> string(39) "http://clan.rocks/api/pay/return/paypal" ["cancel_url"]=> string(39) "http://clan.rocks/api/pay/cancel/paypal" ["auto_bill_amount"]=> string(2) "NO" ["initial_fail_amount_action"]=> string(6) "CANCEL" } } } } ["payer"]=> array(1) { ["payment_method"]=> string(6) "paypal" } ["links"]=> array(2) { [0]=> object(PayPal\Api\Links)#329 (1) { ["_propMap":"PayPal\Common\PPModel":private]=> array(3) { ["href"]=> string(94) "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-44939653MK123321W" ["rel"]=> string(12) "approval_url" ["method"]=> string(8) "REDIRECT" } } [1]=> object(PayPal\Api\Links)#330 (1) { ["_propMap":"PayPal\Common\PPModel":private]=> array(3) { ["href"]=> string(100) "https://api.sandbox.paypal.com/v1/payments/billing-agreements/EC-44939653MK123321W/agreement-execute" ["rel"]=> string(7) "execute" ["method"]=> string(4) "POST" } } } } }
Here is what is finally returned after executing the agreement and such:
string(1486) "{"id":"I-YX83YM13KYWU","state":"Pending","description":"Basic Subscription - $5.00","plan":{"payment_definitions":[{"type":"REGULAR","frequency":"Month","amount":{"currency":"USD","value":"5.00"},"cycles":"0","charge_models":[{"type":"TAX","amount":{"currency":"USD","value":"0.00"}},{"type":"SHIPPING","amount":{"currency":"USD","value":"0.00"}}],"frequency_interval":"1"}],"merchant_preferences":{"setup_fee":{"currency":"USD","value":"0.00"},"max_fail_attempts":"0","auto_bill_amount":"NO"}},"links":[{"href":"https:\/\/api.sandbox.paypal.com\/v1\/payments\/billing-agreements\/I-YX83YM13KYWU\/suspend","rel":"suspend","method":"POST"},{"href":"https:\/\/api.sandbox.paypal.com\/v1\/payments\/billing-agreements\/I-YX83YM13KYWU\/re-activate","rel":"re_activate","method":"POST"},{"href":"https:\/\/api.sandbox.paypal.com\/v1\/payments\/billing-agreements\/I-YX83YM13KYWU\/cancel","rel":"cancel","method":"POST"},{"href":"https:\/\/api.sandbox.paypal.com\/v1\/payments\/billing-agreements\/I-YX83YM13KYWU\/bill-balance","rel":"self","method":"POST"},{"href":"https:\/\/api.sandbox.paypal.com\/v1\/payments\/billing-agreements\/I-YX83YM13KYWU\/set-balance","rel":"self","method":"POST"}],"start_date":"2014-12-07T08:00:00Z","agreement-details":{"outstanding_balance":{"currency":"USD","value":"0.00"},"cycles_remaining":"0","cycles_completed":"0","final_payment_date":"1970-01-01T00:00:00Z","failed_payment_count":"0"}}"
EDIT: For the curious, here is what the agreement shows on PayPal Sandbox:
Upvotes: 3
Views: 2234
Reputation: 528
I had a similar problem, I solved mine not setting a setup Fee, I had 100 USD on paymentDefinition and 10 USD on chargeModel and 1 USD on setupFee, so i think the problem was that i was making a plan of 110 USD but had that 1 USD and the account wouldn´t validate.
Now my payment is in "active" mode.
Hope this helps
Upvotes: 1