我为客户构建了礼品卡系统。我使用了http://paypal.github.io/PayPal-PHP-SDK/sample/
中的paypal api“ PayPal Payments-类似于Classic API中的Express Checkout”我在沙盒帐户上进行了测试,一切正常。在实时模式下,MySQL中5个事务中有3个显示为失败,但Paypal成功处理了所有5个事务。 我本以为可能不是mysql一直都在更新。 我已经附上了付款页面和执行页面的代码。
当我在沙盒上或现场进行测试时。一切都很好。
payment.php
____________
<?php
session_start();
use PayPal\Api\Amount;
use PayPal\Api\Details;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
use PayPal\Api\WebProfile;
use PayPal\Api\InputFields;
use PayPal\Api\ResultPrinter;
date_default_timezone_set('America/Edmonton');
$today=date("ymd");
require __DIR__.'/paypal/bootstrap.php';
require 'admin/lib/CP_DB_PDO.php';
// set session for all user data
if(isset($_POST['fromName'])&&!empty($_POST['fromName'])){
$_SESSION['anna']['fromName']=$_POST['fromName'];
$_SESSION['anna']['fromEmail']=$_POST['fromEmail'];
$_SESSION['anna']['toName']=$_POST['toName'];
$_SESSION['anna']['toEmail']=$_POST['toEmail'];
$_SESSION['anna']['message']=$_POST['message'];
$_SESSION['anna']['amount']=$_POST['amount'];
$_SESSION['anna']['iid']=$_POST['iid'];
$_SESSION['anna']['gcdate']=$_POST['gcdate'];
$_SESSION['anna']['giftcardno']=$today;
$_SESSION['anna']['used']=0;
$_SESSION['anna']['payment']=0;
$amount=$_POST['amount'];
$ins=new CpPdo();
$in_param=$_SESSION['anna'];
try{
$datain=$ins->cpInsert("giftcards", $in_param, "id");}
catch(Exception $ee){
exit("An error has been occured. Please go back and try again");
}
if(!empty($datain)){
$itemid=$datain;
$gcno=$today.$datain;
//update giftcard with actual no
$up_id['id']=$itemid;
$u_param['giftcardno']=$gcno;
$ins->cpUpdate("giftcards", $up_id, $u_param);
unset($_SESSION['anna']);}
else {
exit("An error has been occured. Please go back and try again");
}
}
else {
exit("An error has been occured. Please try again. If problem presists please contact us.");
}
$payer = new Payer();
$payer->setPaymentMethod("paypal");
$item1 = new Item();
$item1->setName('Gift Card Annas Spa')
->setCurrency('CAD')
->setQuantity(1)
->setSku($itemid) // Similar to `item_number` in Classic API
->setPrice($amount);
$itemList = new ItemList();
$itemList->setItems(array($item1));
$details = new Details();
$details->setTax($amount*0.05)
->setSubtotal($amount);
$total=$amount*1.05;
$amount = new Amount();
$amount->setCurrency("CAD")
->setTotal($total)
->setDetails($details);
// Parameters for input fields customization.
$flowConfig = new \PayPal\Api\FlowConfig();
$flowConfig->setUserAction("commit");
$inputFields = new InputFields();
// Enables the buyer to enter a note to the merchant on the PayPal page during checkout.
$inputFields->setNoShipping(1)->setAddressOverride(0);
// Determines whether or not PayPal displays shipping address fields on the experience pages. Allowed values: 0, 1, or 2. When set to 0, PayPal displays the shipping address on the PayPal pages.
// When set to 1, PayPal does not display shipping address fields whatsoever. When set to 2, if you do not pass the shipping address, PayPal obtains it from the buyer’s account profile. For digital goods, this field is required, and you must set it to 1.
// Determines whether or not the PayPal pages should display the shipping address and not the shipping address on file with PayPal for this buyer.
// Displaying the PayPal street address on file does not allow the buyer to edit that address. Allowed values: 0 or 1.
// When set to 0, the PayPal pages should not display the shipping address. When set to 1, the PayPal pages should display the shipping address.
$webProfile = new WebProfile();
$webProfile->setName("Anna Spa".uniqid())
->setInputFields($inputFields)
->setFlowConfig($flowConfig);
try {
// Use this call to create a profile.
$createProfileResponse = $webProfile->create($apiContext);
} catch (\PayPal\Exception\PayPalConnectionException $ex) {
// NOTE: PLEASE DO NOT USE RESULTPRINTER CLASS IN YOUR ORIGINAL CODE. FOR SAMPLE ONLY
// ResultPrinter::printError("Created Web Profile", "Web Profile", null, $request, $ex);
exit(1);
}
// $createProfileResponse = $webProfile->create($apiContext);
//$webProfile = WebProfile::get($createProfileResponse->getId(), $api);
//
$transaction = new Transaction();
$transaction->setAmount($amount)
->setItemList($itemList)
->setDescription("Anna Spa Gift Card")
->setInvoiceNumber($gcno);
//Redirect urls
//Set the urls that the buyer must be redirected to after payment approval/ cancellation.
function getBaseUrl(){
$ur="http://localhost/spagift";
return $ur;
}
$baseUrl = getBaseUrl();
$redirectUrls = new RedirectUrls();
$redirectUrls->setReturnUrl("$baseUrl/ExecutePayment.php?success=true")
->setCancelUrl("$baseUrl/ExecutePayment.php?success=false");
//Payment
//A Payment Resource; create one using the above types and intent set to 'sale'
$payment = new Payment();
$payment->setIntent("sale")
->setPayer($payer)
->setRedirectUrls($redirectUrls)
->setTransactions(array($transaction))
->setExperienceProfileId($createProfileResponse->getId());
//Create Payment
//Create a payment by calling the 'create' method passing it a valid apiContext. (See bootstrap.php for more on ApiContext) The return object contains the state and the url to which the buyer must be redirected to for payment approval
try {
$payment->create($apiContext);
//save payment id into transaction table
$tablename="transactions_paypal";
$value['payment_id']=$payment->getId();
$value['card_id']=$gcno;
$value['hash']= md5($value['payment_id']);
$_SESSION['paypal_hash']=$value['hash'];
$_SESSION['itemno']=$datain;
$_SESSION['gcno']=$gcno;
$ins->cpInsert($tablename, $value); // this is a class i wrote using php pdo
} catch (PPConnectionException $ex) {
//NOTE: PLEASE DO NOT USE RESULTPRINTER CLASS IN YOUR ORIGINAL CODE. FOR SAMPLE ONLY
echo $ex->getData();
//ResultPrinter::printError("Created Payment Using PayPal. Please visit the URL to Approve.", "Payment", null, $request, $ex);
exit("An error has been occured. Please go back and try again");
}
//Get redirect url
//The API response provides the url that you must redirect the buyer to. Retrieve the url from the $payment->getApprovalLink() method
$approvalUrl = $payment->getApprovalLink();
foreach ($payment->getLinks() as $link) {
if($link->getRel()=='approval_url'){
$redirectUrl =$link->getHref();
}
}
header('Location:'.$redirectUrl);
ExecutePayment.php
____________________
<?php
session_start();
require __DIR__.'/paypal/bootstrap.php';
require 'admin/lib/CP_DB_PDO.php';
use PayPal\Api\Amount;
use PayPal\Api\Details;
use PayPal\Api\Payment;
use PayPal\Api\PaymentExecution;
use PayPal\Api\Transaction;
$successUrl="success.php";
//Approval Status
//Determine if the user approved the payment or not
if (isset($_GET['success']) && $_GET['success'] == 'true') {
//Get the payment Object by passing paymentId payment id was previously stored in session in CreatePaymentUsingPayPal.php
$paymentId = $_GET['paymentId'];
$payment = Payment::get($paymentId, $apiContext);
$payerId=$_GET['PayerID'];
try {
//Execute the payment (See bootstrap.php for more on ApiContext)
$execution= new PaymentExecution();
$execution->setPayerId($payerId);
$result = $payment->execute($execution, $apiContext);//user charged here
print_r($result);
try {
$payment = Payment::get($paymentId, $apiContext);
} catch (Exception $ex) {
echo "payment Error";
// ResultPrinter::printError("Get Payment", "Payment", null, null, $ex);
exit(1);
}
} catch (Exception $ex) {
//NOTE: PLEASE DO NOT USE RESULTPRINTER CLASS IN YOUR ORIGINAL CODE. FOR SAMPLE ONLY
echo "Payment Error 2: Paypal Rejected the payment";
exit(1);
}
//update transaction table
$cp=new CpPdo();
//update giftcard table
$id=$_SESSION['itemno'];
$uid['id']=$id;
$upparam['payment']=1;
//$upparam['giftcardno']=$_SESSION['gcno'];
unset($_SESSION['gcno']);
unset($_SESSION['itemno']);
$gup=$cp->cpUpdate("giftcards", $uid, $upparam);
/////
$u_id['hash']=$_SESSION['paypal_hash'];
$up_param['complete']=1;
unset($_SESSION['paypal_hash']);
$tup=$cp->cpUpdate("transactions_paypal", $u_id, $up_param);
//header('Location:'.$successUrl);
//return $payment;
} else {
//NOTE: PLEASE DO NOT USE RESULTPRINTER CLASS IN YOUR ORIGINAL CODE. FOR SAMPLE ONLY
echo "user cancelled";
//ResultPrinter::printResult("User Cancelled the Approval", null);
exit;
}