I am calling SetExpressCheckout and handing in some tax. The Grand total in the paypal checkout screen reflects the tax (as expected) but there is no line item showing the tax. This is very confusing for customers. It appears like the grand total is "just higher" than the item price, for no apparent reason. I can't believe paypal would build it this way, so I assume I must be doing something wrong.
Here's a screenshot:
Here is my REQUEST:
VERSION = 97.0
METHOD = SetExpressCheckout
RETURNURL = http://[removed...]
CANCELURL = http://[removed...]
PAYMENTREQUEST_0_PAYMENTACTION = Sale
PAYMENTREQUEST_0_CURRENCYCODE = USD
PAYMENTREQUEST_0_ITEMAMT = 1
L_PAYMENTREQUEST_0_NAME0 = Widget1
L_PAYMENTREQUEST_0_NUMBER0 = Widget1
L_PAYMENTREQUEST_0_AMT0 = 1
PAYMENTREQUEST_0_TAXAMT = 0.06
PAYMENTREQUEST_0_AMT = 1.06
L_PAYMENTREQUEST_0_QTY0 = 1
L_PAYMENTREQUEST_0_ITEMCATEGORY0 = Digital
SOLUTIONTYPE = Sole
REQCONFIRMSHIPPING = 0
NOSHIPPING = 1
I also tried adding tax as an add'l "L_" line item for tax, but that makes it worse. It increases the line item itself by the tax amount, so the customer doesn't know they're paying tax, they just think the item price is higher.
Please help.
Don't know if you still need help but I found a way to add tax simply by adding the tax as an additional item.
This also allowed me to name the tax....:
// to add anothe item, uncomment the lines below and comment the line above
$items[] = array('name' => 'TVA', 'amt' => $tvaAmount1, 'qty' => 1);
// $items[] = array('name' => 'Item Name2', 'amt' => $itemAmount2, 'qty' => 1);
$paymentAmount = $paymentAmount + $tvaAmount1;
Related
I have to update the credit card information of the user in my project using braintree update method.
The code segment of my controller for the updation of the card is below -
case 'update':
$expirationMonth = $this->input->post('expiration_month');
$expirationYear = $this->input->post('expiration_year');
if (!empty($expirationMonth) && !empty($expirationYear)) {
if (date('Y') > $expirationYear) {
die('expired');
} else if ($expirationYear == date('Y')) {
if (date('m') > $expirationMonth)
die('expired');
}
}
$cardId = $this->input->post('cardId');
$cardNumber = $this->input->post('card_num');
$streetAddress = $this->input->post('street_add');
$cardCity = $this->input->post('card_city');
$cardState = $this->input->post('card_state');
$postalCode = $this->input->post('postal_code');
$customerId = $this->input->post('customer_id');
$vaultToken = $this->input->post('vault_token');
$cvvCode = $this->input->post('cvv_code');
$data['default_status'] = $this->input->post('default_status');
$data['card_type'] = $this->input->post('cardType');
$this->load->library("braintreelib");
$result = Braintree_Customer::update($customerId, array(
//we can create a credit card at the same time
'creditCard' => array(
//'cardholderName' => $this->input->post('cardholder_name'),
//'number' => $cardNumber,
'expirationMonth' => $expirationMonth,
'expirationYear' => $expirationYear,
'cvv' => $cvvCode,
'billingAddress' => array(
/* Optional Information you can supply */
'streetAddress' => $streetAddress,
'locality' => $cardCity,
'region' => getUsStateName($cardState)->abbrev,
'postalCode' => $postalCode,
),
'options' => array('verifyCard' => true)
)
));
if (isset($cardId)) {
if($result->success){
$this->load->model('updatedetails_model');
if($data['default_status']){
$this->common->saveDetails(TBL_RS_PAYMENTDETAILS, array('default_status' => 0, 'card_type' => $cardType), array('currentuserid' => $currentUserId, 'currentroleid' => $this->input->post('roleId')));
}
$cardDetailId = $this->updatedetails_model->addedit_carddetails($data, $cardId);
if (!$cardDetailId) {
echo 'error';
exit;
}
}else{
foreach ($result->errors->deepAll() as $error) {
$errorFound = $error->message . "<br />";
}
//echo $errorFound ;
echo $errorFound;
exit;
}
} else {
echo 'invalidcarddetails';
exit;
}
$details['carddetails'] = $this->profile->getUserCardDetailsByUserId($currentUserId);
foreach($details['carddetails'] as $index => $value){
$paymentMethod = Braintree_PaymentMethod::find(base64_decode($value->vault_token));
$details['carddetails'][$index]->lastDigit = $paymentMethod->last4;
$details['carddetails'][$index]->cardType = $paymentMethod->cardType;
$details['carddetails'][$index]->cardholderName = ucfirst($paymentMethod->cardholderName);
}
$this->data['carddetails'] = $details['carddetails'];
echo $b = $this->load->view('operatorCardListing', $this->data, TRUE);
break;
When I am trying to run this code, I am getting the error -
Credit card must include number, paymentMethodNonce, or venmoSdkPaymentMethodCode.
My requirement is to update the credit card information without putting the card number.
Is it possible to update the card without credit card number ?
Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.
You are able to update a credit card without specifying a credit card number. Braintree recommends doing this with the payment method functions instead of the credit card object to help you avoid handling raw credit card data on your website.
In the code that you've posted, you're making a customer update call rather than a credit card update call. When you make your customer update call, you're sending an array of credit cards. Braintree will try to update the customer by adding the cards in that array to the customer's record. The customer update call does not signal to the gateway that the cards on the customer should be updated. Rather than a customer update call, you'll want to use a [payment method update call][pm_upadte].
To update only a portion of the card, such as changing only the expiration date or CVV, you can use a payment method nonce. Create a payment method nonce by tokenizing only the details that you want to change. Once you have a nonce that only references the details you want to change, you can pass that into a payment method update call. This is what it might look like in php:
$result = Braintree_PaymentMethod::update('the_token', [
'paymentMethodNonce' => 'nonce_from_your_client'
]);
I am really getting confused with BillingFrequency , BillingPeriod , TotalBillingCycles , What i am trying to achive is set up monthly billing for 12 months.
$paymentBillingPeriod = new BillingPeriodDetailsType();
$paymentBillingPeriod->BillingFrequency = "1"; //can not be more than a year
$paymentBillingPeriod->BillingPeriod = "Year";
$paymentBillingPeriod->TotalBillingCycles ="12";
$paymentBillingPeriod->Amount = new BasicAmountType($currencyCode, 18); // GET Amount from Session
$paymentBillingPeriod->ShippingAmount = new BasicAmountType($currencyCode, "0");
$paymentBillingPeriod->TaxAmount = new BasicAmountType($currencyCode, "0");
This is the error response from API
Billing period must be one of Day, Week, SemiMonth, or Year Billing
frequency must be > 0 and be less than or equal to one year
What i am doing wrong ?
Source
$currencyCode = "USD";
$billingStartDate = date("Y-m-d\TH:i:s\Z");
$subscriberName = "Name";// Session var
$token = "" ; //
$amount = "10.00"
$RPProfileDetails = new RecurringPaymentsProfileDetailsType();
$RPProfileDetails->SubscriberName = $subscriberName;
$RPProfileDetails->BillingStartDate = $billingStartDate;
$activationDetails = new ActivationDetailsType();
$paymentBillingPeriod = new BillingPeriodDetailsType();
$paymentBillingPeriod->BillingFrequency = '12';
$paymentBillingPeriod->BillingPeriod = 'Month';
$paymentBillingPeriod->Amount = new BasicAmountType($currencyCode, $amount);
$paymentBillingPeriod->ShippingAmount = new BasicAmountType($currencyCode, 0.0);
$paymentBillingPeriod->TaxAmount = new BasicAmountType($currencyCode, 0.0);
$scheduleDetails = new ScheduleDetailsType();
$scheduleDetails->Description = "This is recurring payment";
$scheduleDetails->ActivationDetails = $activationDetails;
$createRPProfileRequestDetail = new CreateRecurringPaymentsProfileRequestDetailsType();
$createRPProfileRequestDetail->Token = $token;
$createRPProfileRequestDetail->ScheduleDetails = $scheduleDetails;
$createRPProfileRequestDetail->RecurringPaymentsProfileDetails = $RPProfileDetails;
$createRPProfileRequest = new CreateRecurringPaymentsProfileRequestType();
$createRPProfileRequest->CreateRecurringPaymentsProfileRequestDetails = $createRPProfileRequestDetail;
$createRPProfileReq = new CreateRecurringPaymentsProfileReq();
$createRPProfileReq->CreateRecurringPaymentsProfileRequest = $createRPProfileRequest;
$paypalService = new PayPalAPIInterfaceServiceService(Configuration::getAcctAndConfig());
try {
/* wrap API method calls on the service object with a try catch */
$createRPProfileResponse = $paypalService->CreateRecurringPaymentsProfile($createRPProfileReq);
} catch (Exception $ex) {
include_once("Error.php");
exit;
}
Responce
Ack :
Failure
ProfileID :
PayPal\PayPalAPI\CreateRecurringPaymentsProfileResponseType Object
(
[CreateRecurringPaymentsProfileResponseDetails] => PayPal\EBLBaseComponents\CreateRecurringPaymentsProfileResponseDetailsType Object
(
[ProfileID] =>
[ProfileStatus] =>
[TransactionID] =>
[DCCProcessorResponse] =>
[DCCReturnCode] =>
)
[Timestamp] => 2015-10-07T09:14:22Z
[Ack] => Failure
[CorrelationID] => 1d7177ca754
[Errors] => Array
(
[0] => PayPal\EBLBaseComponents\ErrorType Object
(
[ShortMessage] => Invalid billing period.
[LongMessage] => Billing period must be one of Day, Week, SemiMonth, or Year
[ErrorCode] => 11518
[SeverityCode] => Error
[ErrorParameters] =>
)
[1] => PayPal\EBLBaseComponents\ErrorType Object
(
[ShortMessage] => Invalid billing frequency
[LongMessage] => Billing frequency must be > 0 and be less than or equal to one year
[ErrorCode] => 11516
[SeverityCode] => Error
[ErrorParameters] =>
)
[2] => PayPal\EBLBaseComponents\ErrorType Object
(
[ShortMessage] => Invalid amount
[LongMessage] => Bill amount must be greater than 0
[ErrorCode] => 11519
[SeverityCode] => Error
[ErrorParameters] =>
)
)
[Version] => 106.0
[Build] => 000000
)
It will work if you modified the BillingFrequency and BillingPeriod combination and leave all the rest parameters as below,
$paymentBillingPeriod = new BillingPeriodDetailsType();
//$paymentBillingPeriod->BillingFrequency = $_REQUEST['billingFrequency'];
//$paymentBillingPeriod->BillingPeriod = $_REQUEST['billingPeriod'];
$paymentBillingPeriod->BillingFrequency = "12";
$paymentBillingPeriod->BillingPeriod = "Month";
$paymentBillingPeriod->TotalBillingCycles = $_REQUEST['totalBillingCycles'];
$paymentBillingPeriod->Amount = new BasicAmountType($currencyCode, $_REQUEST['paymentAmount']);
$paymentBillingPeriod->ShippingAmount = new BasicAmountType($currencyCode, $_REQUEST['paymentShippingAmount']);
$paymentBillingPeriod->TaxAmount = new BasicAmountType($currencyCode, $_REQUEST['paymentTaxAmount']);
In your case, the explanation would be (you may find the same in the code comments right above the lines you've modified):
BillingFrequency: "How many periods you want to charge the customer"
BillingPeriod: "Define your unit of period"
TotalBillingCycles: "Optional in this case, as the combiniation of the above 2 cannot exceed one year"
*Be noted that the SDK sample invokes the CreateRecurringPaymentsProfile API with form data posted from merchant-sdk-php/samples/RecurringPayments/CreateRecurringPaymentsProfile.html.php, so if you'd like to customized your own payload function, please make sure all the mandatory paramerters are passed.
Refer to the API Specs Here, look for all the "(Required)" parameters in the description, and cross-check with your codes.
Judging by the documentation from paypal;
https://developer.paypal.com/docs/classic/api/merchant/CreateRecurringPaymentsProfile_API_Operation_NVP/
Your variables should be looking like;
$paymentBillingPeriod->BillingFrequency = "12"; //can not be more than a year
$paymentBillingPeriod->BillingPeriod = "Month";
This is because the period of payment is monthly and the frequency is 12, which rounds to 1 year.
As per the documentation quote;
The combination of billing frequency and billing period must be less than or equal to one year. For example, if the billing cycle is Month, the maximum value for billing frequency is 12. Similarly, if the billing cycle is Week, the maximum value for billing frequency is 52.
Edit
Doing it this way means you can omit the TOTALBILLINGCYCLES value, which cleans up the code as you have one less line to contend with.
I am integrating PayPal Express Checkout for Digital Goods on my website and I am having trouble displaying the items which the user has selected on the PayPal review page -- the item displays but its name is cut off at 19 characters, which is not very lengthy for identifying something.
Is this just a limit of the interface, or is there something I can do to make the full name (or at least 40 or so characters of it) display? I know I'm passing in the full string because it shows if I hover over the truncated description.
If it is a limit of the interface, is it always 19 characters in every browser, including mobile? Is it by em-length? If I know this is the hard limit I can massage the item names so that I don't appear to be selling "Attending Membershi".
I'm using the basic code provided by the PayPal integration wizard. I'm filling my $items array to pass to SetExpressCheckoutDG in PHP like so:
$items[] = array('name' => 'Attending Membership for [convention and date]', 'amt' => $attending_cost, 'qty' => 1);
$resArray = SetExpressCheckoutDG( $paymentAmount, $currencyCodeType, $paymentType, $returnURL, $cancelURL, $items );
and then retrieving them with GetExpressCheckoutDetails and resending them via ConfirmPayment:
$res = GetExpressCheckoutDetails( $_REQUEST['token'] );
$items = array();
$i = 0;
while(isset($res["L_PAYMENTREQUEST_0_NAME$i"])) {
$items[] = array('name' => $res["L_PAYMENTREQUEST_0_NAME$i"], 'amt' => $res["L_PAYMENTREQUEST_0_AMT$i"], 'qty' => $res["L_PAYMENTREQUEST_0_QTY$i"]);
$i++;
}
$resArray = ConfirmPayment ( $token, $paymentType, $currencyCodeType, $payerID, $finalPaymentAmount, $items );
and getting this: http://i.imgur.com/9ST9mm7.png
PayPal checkout pages display the item name based on the layout that is rendered.
Item length supported for :
Digital Goods - 19 characters
Express Checkout (Physical) old layout = 35 characters
Express Checkout (Physical) new layout = 13 characters
In-Context Checkout - 19 Characters.
It's the intended behaviour to not to show the entire character length and shows upon hover
I'm trying to use a negative amount with the PayPal Adaptive Payments API. To start with, this seems to work:
'item' => [
{
'itemPrice' => '25.00',
'name' => 'Cryptex - 16Gb USB Drive',
'price' => '25',
'itemCount' => 1
},
{
'quantity' => 1,
'name' => 'Special Discount',
'price' => '-2.50'
},
{
'itemPrice' => '5.00',
'name' => 'Shipping',
'price' => '5.00',
'itemCount' => 1
}
]
Here is an example of what I see after submitting this as JSON, and updating the items:
As you can see, the price IS correct ... yet there is no sign of the discounted amount? Its obviously taking it into account - otherwise the price would have been £30, not £27.50 (which is after the £2.50 discount)
What gives? Is this a bug in PayPals system?
FWIW, the emails are also broken - they don't show the discount amount at all.
UPDATE: I've opened a ticket with PayPal tech support, as I'm pretty sure this is a bug with their system, and not something that can be fixed this end :( Damn annoying!
UPDATE 2: Reply from PayPal:
PayPal Adaptive Payments do not support negative item values. Since you did not pass the <itemPrice> in your API Call, the system did not throw the following error message:
[errorId] => 580022
[domain] => PLATFORM
[subdomain] => Application
[severity] => Error
[category] => Application
[message] => Invalid request parameter: itemPrice cannot be negative
I can see that the following was submitted to PayPal:
<item>
<name>Special Discount</name>
<identifier></identifier>
<price>-2.50</price>
<itemPrice></itemPrice>
<itemCount></itemCount>
<any>[quantity: null]</any>
</item>
This object is basically incomplete and in order to apply discounts, you should apply them > onto the price for the main item and then submit it to PayPal.
I'm really not sure what they're suggestion I do? An example cart, would be:
Item 1 - £10
Item 2 - £20
Item 3 - £50
Item 4 - £10
Delivery - £5
Total - £95
As an encouragement, we sometimes will offer coupons... so it could be "£10 off orders over £50". So in the above case above, it would drop the overall price to £85.
I'm really not sure what they are suggesting as an alternative?
Interesting. Normal payments don't have that restriction (I pass a negative amount item just like what you describe on a frequent basis).
What they're telling you to do is take the discount off another item. So your example cart with that discount would be
Item 1 - £10
Item 2 - £20
Item 3 - £40 <-- Removed £10 discount
Item 4 - £10
Delivery - £5
Total - £85 <-- total reflects this
I am new to paypal integration and doing ipn integration right now.
I am a little confused regarding payment_status processed and completed values according to their site.
Completed: The payment has been completed, and the funds have been
added successfully to your account balance.
Processed: A payment has been accepted.
Dont really get this?
here are my questions
if it sends an ipn with payment status processed, will it send
another ipn with payment status completed?
when does it send a processed ipn and when does it send a completed
ipn?
for which status should you consider a item(s) paid for? completed or processed?
thanks in advance
I'm pretty sure the only time you'd see processed is if you send a payment to an account that doesn't exist yet, or if you send to an account where they have their settings configured to have them accept any payments they receive.
In such a case, when the payment takes place it will have a "status_n" of "unclaimed" and the payment_status would be processed. Note that the n would be the number of the payment in cases where you had more than 1. For example, with MassPay. In fact, here's a sample I was able to find in my IPN logs...
txn_type = masspay
payment_gross_1 = 1500.00
payment_date = 09:52:38 Dec 23, 2012 PST
last_name = Angell
mc_fee_1 = 1.00
masspay_txn_id_1 = 9N3213015V198645H
receiver_email_1 = info#acexlogics.com
residence_country = US
verify_sign = AueDyRcHXo48zG3juE2C-Z801Wi9AhrDKrUI2Dxtkt8T9UVV4DHECvEC
payer_status = verified
test_ipn = 1
payer_email = sandbo_1215254764_biz#angelleye.com
first_name = Drew
payment_fee_1 = 1.00
payer_id = ATSCG2QMC9KAU
payer_business_name = Drew Angell's Test Store
payment_status = Processed
status_1 = Unclaimed
mc_gross_1 = 1500.00
charset = windows-1252
notify_version = 3.7
mc_currency_1 = USD
unique_id_1 = 3
ipn_track_id = a8817fe5573f3
This particular IPN was from a MassPay request that included only a single receiver. It came back as "processed" and "unclaimed" because the receiver_email didn't have an existing PayPal account yet.
Here's a separate IPN for a MassPay request that included 3 receivers and all had accounts, so they all came back as completed.
[payer_id] => ATSCG2QMC9KAU
[payment_date] => 21:37:28 Jan 01, 2013 PST
[payment_gross_1] => 10.00
[payment_gross_2] => 10.00
[payment_gross_3] => 10.00
[payment_status] => Processed
[receiver_email_1] => andrew_1342623385_per#angelleye.com
[receiver_email_2] => usb_1329725429_biz#angelleye.com
[charset] => windows-1252
[receiver_email_3] => andrew_1277258815_per#angelleye.com
[mc_currency_1] => USD
[masspay_txn_id_1] => 53E82259BP7975932
[mc_currency_2] => USD
[masspay_txn_id_2] => 4AS03088H50506411
[mc_currency_3] => USD
[masspay_txn_id_3] => 6A492363UM676994C
[first_name] => Drew
[unique_id_1] =>
[notify_version] => 3.7
[unique_id_2] =>
[unique_id_3] =>
[payer_status] => verified
[verify_sign] => A2Kn5CkYqzBOhX.t-MhTsUEnQbXNAs-mp6LyPmPY1bKAQnyPlKUqiOZN
[payer_email] => sandbo_1215254764_biz#angelleye.com
[payer_business_name] => Drew Angell's Test Store
[last_name] => Angell
[status_1] => Completed
[status_2] => Completed
[status_3] => Completed
[txn_type] => masspay
[mc_gross_1] => 10.00
[mc_gross_2] => 10.00
[mc_gross_3] => 10.00
[payment_fee_1] => 0.20
[residence_country] => US
[test_ipn] => 1
[payment_fee_2] => 0.20
[payment_fee_3] => 0.20
[mc_fee_1] => 0.20
[mc_fee_2] => 0.20
[mc_fee_3] => 0.20
[ipn_track_id] => e1938454f1e98
I don't have time to setup a scenario where the account doesn't exist and is then created and accepted, but I'm fairly certain you would indeed get another IPN showing it was completed.
Long story short, I would make sure to look for "completed" as oppose to "processed" when handling post-payment processing.