This is the scenario, User instantiate a paypal transaction (eg.$100) but returns to the site without cancelling from paypal and decided to choose a different amount (eg.$25). When it redirects to paypal it still charges $100. Is there any way of updating that amount?
//CODE SNIPPET
$transactionDetails = array(
"amount" => array(
"total" => $total,
"currency" => PAYPAL_CURRENCY
),
"description" => "Adding $".$total.PAYPAL_CURRENCY
);
$returnUrl = site_url('referral/addFundForUser');
$cancelUrl = site_url('referral/');
$paymentMethod = "paypal";
$data = array(
"intent" => "sale",
"redirect_urls" => array(
"return_url" => $returnUrl,
"cancel_url" => $cancelUrl
),
"payer" => array(
"payment_method" => $paymentMethod
),
"transactions" => array($transactionDetails)
);
$header = array(
'Content-Type: application/json',
'Authorization: '.$tokenType. ' '.$accessToken
);
$url = $this->url.'v1/payments/payment';
return $this->doCurlCall($url,$data,$header);
FYI:
I was saving user $transactionDetails in Session so that when paypal redirects back to me, I can update my payment Log.
if (!$this->getTransactionInfo() ){
$newTransaction = $this->paypal->startSale($this->getTokenType(),$this->getAccessToken(),$transactionDetails);
$transactionInfo = array(
"paymentTransactionId" => $newTransaction->id,
"total" => $total
);
foreach($newTransaction->links as $key=>$value){
if (strcmp($value->rel,'self') == 0){
$transactionInfo['self'] = $value->href;
}else if (strcmp($value->rel,'approval_url') == 0){
$transactionInfo['approval'] = $value->href;
$data['approval_url'] = $value->href;
}else if (strcmp($value->rel,'execute') == 0){
$transactionInfo['execute'] = $value->href;
}
}
$this->setTransactionInfo($transactionInfo,true);//SAVES IN SESSION
$paymentTransactionId = $newTransaction->id;
}else{
$newTransaction = $this->getTransactionInfo();
$paymentTransactionId = $newTransaction['paymentTransactionId'];
}
$successMsg = "Paypal Transaction Instantiated";
if ($this->insertPaymentLog($paymentTransactionId,$total,$payerId="",false,$successMsg,"",$transactionType)){
}
$data['transactionDetails'] = $transactionDetails;
$approval = $this->getTransactionInfo()['approval'];
redirect($approval);
FIX
if (!$this->getTransactionInfo() || $total != $this->getTransactionInfo()['total']){
Related
I have a problem in my wordpress, i use stripe and i have this error message : "This customer has no attached payment source " but i don't understand why. In dev environment i had no problem and now in prod i have this issue. For information i use the card number 4242 4242 4242 4242 for testing.
Thanks a lot for your help
if(isset($_POST['action']) && $_POST['action'] == 'stripe' && wp_verify_nonce($_POST['stripe_nonce'], 'stripe-nonce')) {
global $stripe_options, $post;
// load the stripe libraries
require_once(STRIPE_BASE_DIR . '/init.php');
// retrieve the token generated by stripe.js
$token = $_POST['stripeToken'];
$amount = base64_decode($_POST['amount'])*100;
$email = $_POST['email'];
$plan_nickname = $_POST['plan_nickname'];
$plan_id = $_POST['plan_id'];
$nom = $_POST['name'];
$prenom = $_POST['prenom'];
$adresse = $_POST['address-line1'];
$ville = $_POST['address-city'];
$zip = $_POST['address-zip'];
// check if we are using test mode
if(isset($stripe_options['test_mode']) && $stripe_options['test_mode']) {
$secret_key = $stripe_options['test_secret_key'];
} else {
$secret_key = $stripe_options['live_secret_key'];
}
// attempt to charge the customer's card
try {
\Stripe\Stripe::setApiKey($secret_key);
$product = \Stripe\Product::create([
'name' => $stripe_options['product_name'],
'type' => 'service',
]);
$plan = \Stripe\Plan::create([
'product' => $stripe_options['product_key'],
'nickname' => $plan_nickname,
'interval' => 'month',
'currency' => 'eur',
'amount' => $amount,
]);
$customer = \Stripe\Customer::create([
'email' => $email,
'source' => $token,
'description' => $plan_nickname,
]);
$subscription = \Stripe\Subscription::create([
'customer' => $customer->id,
'items' => [['plan' => $plan_id]],
]);
// redirect on successful payment
$redirect = add_query_arg('payment', 'paid', $_POST['redirect']);
} catch (Exception $e) {
// redirect on failed payment
//$redirect = add_query_arg('payment', 'failed', $_POST['redirect_failed']);
var_dump($e);
}
// redirect back to our previous page with the added query variable
wp_redirect($redirect); exit;
}
}
Check the plan on Stripe. If the plan has a trial period you need to create the subscription with the trial period. I am using laravel cashier and react-stripe-checkout and this worked for me:
$user->newSubscription('main', 'basic')
->trialDays(30)
->create($request->token);
Recently i'm working on a laravel project which i choose to use srmklive/laravel-paypal as my paypal payment gateway plugin, but i found that i cannot add Tax and shipping fees, i have read the readme.doc multiple time and also check the paypal documentation, but i still confused on how to add the tax and shipping fees.
Did any one know how to add these data when setExpresssCheckout?
here is my code:
$provider = new ExpressCheckout;
$provider = PayPal::setProvider('express_checkout');
$itemsArr = $data = [];
// add items
foreach ($order->orderProduct as $order_product) {
array_push($itemsArr, [
'name' => $order_product->product->name,
'price' => $order_product->price,
'qty' => $order_product->quantity
]);
}
// add shipping fees
array_push($itemsArr, [
'name' => "Shipping Method : ".$order->shipping_method,
'price' => $order->shipping_fees,
'qty' => 1
]);
$data["items"] = $itemsArr;
$data['invoice_id'] = 1;
$data['invoice_description'] = "Order #1 Invoice";
$data['return_url'] = url('/payment/success');
$data['cancel_url'] = url('/cart');
$total = 0;
foreach($data['items'] as $item) {
$total += $item['price']*$item['qty'];
}
$data['total'] = $total;
$options = [
'BRANDNAME' => 'Ulife',
'LOGOIMG' => asset("images\ulifelanding.png"),
'CHANNELTYPE' => 'Merchant'
];
$response = $provider->setCurrency('MYR')->addOptions($options)->setExpressCheckout($data);
Ps: i also asked on the github, but still confused.
I don't know who still needs an answer for this question, but I share ("srmklive/paypal": "~1.0").
go to ExpressCheckout.php and go to setExpressCheckout add this :
'PAYMENTREQUEST_0_AMT' => $data['total']+$data['tax'],
'PAYMENTREQUEST_0_TAXAMT' => $data['tax'],
and you checkoutData put now:
'tax'=>xx
call your provider with addOptions:
example:
$options = [
'BRANDNAME' => 'MyBrand',
'LOGOIMG' => 'https://example.com/mylogo.png',
'CHANNELTYPE' => 'Merchant',
];
$provider->addOptions($options)->setExpressCheckout($checkoutData)
The Stripe API explains how to create an account and update it:
https://stripe.com/docs/api#external_accounts
The Stripe Api also explains how to create a bank account:
https://stripe.com/docs/api#account_create_bank_account
I am trying to create a bank account for a connected account, but unfortunately I keep blocked with this error message:
Missing required param: external_account.
Here is how I proceeded to create the connected account:
public function test_stripe_create_connected_account(Request $request)
{
\Stripe\Stripe::setApiKey("sk_test_...");
$acct = \Stripe\Account::create(array(
"country" => "CH",
"type" => "custom",
"email" => "test#test.ch"
));
}
Then I complete the account by updating it on this way:
public function test_stripe_update_account(Request $request)
{
try {
\Stripe\Stripe::setApiKey("sk_test_...");
$account = \Stripe\Account::retrieve("acct_1BTRCOB5XLEUUY47");
$account->support_email = "victor#krown.ch";
$account->support_phone = "0041764604220";
$account->legal_entity->type = "company";
$account->legal_entity->business_name = "Barbosa Duvanel SARL";
$account->legal_entity->additional_owners = NULL;
//NAME
$account->legal_entity->first_name = "Victor";
$account->legal_entity->last_name = "Duvanel";
//BIRTH DATE
$account->legal_entity->dob->day = 25;
$account->legal_entity->dob->month = 3;
$account->legal_entity->dob->year = 1988;
//ADDRESS
$account->legal_entity->address->city = "Genève";
$account->legal_entity->address->country = "CH";
$account->legal_entity->address->line1 = "Av de la Roseraie 76A";
$account->legal_entity->address->line2 = "Genève";
$account->legal_entity->address->postal_code = "1207";
$account->legal_entity->address->state = "Genève";
//PERSONAL ADDRESS
$account->legal_entity->personal_address->city = "Genève";
$account->legal_entity->personal_address->country = "CH";
$account->legal_entity->personal_address->line1 = "Av de la Roseraie 76A";
$account->legal_entity->personal_address->line2 = "Genève";
$account->legal_entity->personal_address->postal_code = "1207";
$account->legal_entity->personal_address->state = "Genève";
//GENERAL CONDITIONS ACCEPTATION
$account->tos_acceptance->date = time();
$account->tos_acceptance->ip = $_SERVER['REMOTE_ADDR'];
$account->save();
$message = 'OK';
$status = true;
} catch (\Exception $error) {
$message = $error->getMessage();
$status = false;
}
$results = (object)array(
'message' => $message,
'status' => $status,
);
$response = response()->json($results, 200);
return $response;
}
And finally, I am trying to attach a new bank account to my user like that:
public function test_stripe_create_bank_account(Request $request)
{
try {
\Stripe\Stripe::setApiKey("sk_test_...");
$account = \Stripe\Account::retrieve("acct_1BSoOaGS1D3TfSN5");
$account->external_accounts->create(
array(
"object" => "bank_account",
"account_number" => "CH820024024090647501F",
"country" => "CH",
"currency" => "CHF",
)
);
$message = 'OK';
$status = true;
} catch (\Exception $error) {
$message = $error->getMessage();
$status = false;
}
$results = (object)array(
'message' => $message,
'status' => $status,
);
$response = response()->json($results, 200);
return $response;
}
What am I doing wrong?
Any help would be appreciated!
You need to change your external account creation request to wrap the array under the external_account parameter name, like this:
$account->external_accounts->create(array(
"external_account" => array(
"object" => "bank_account",
"account_number" => "CH820024024090647501F",
"country" => "CH",
"currency" => "CHF",
)
));
I am using this below code in my existing project. You can use this code without
any fear
public function Stripe(){
Stripe\Stripe::setApiKey(env('STRIPE_SECRET'));
try {
// first create bank token
$bankToken = \Stripe\Token::create([
'bank_account' => [
'country' => 'GB',
'currency' => 'GBP',
'account_holder_name' => 'Soura Sankar',
'account_holder_type' => 'individual',
'routing_number' => '108800',
'account_number' => '00012345'
]
]);
// second create stripe account
$stripeAccount = \Stripe\Account::create([
"type" => "custom",
"country" => "GB",
"email" => "<Mail-Id>",
"business_type" => "individual",
"individual" => [
'address' => [
'city' => 'London',
'line1' => '16a, Little London, Milton Keynes, MK19 6HT ',
'postal_code' => 'MK19 6HT',
],
'dob'=>[
"day" => '25',
"month" => '02',
"year" => '1994'
],
"email" => '<Mail-Id>',
"first_name" => 'Soura',
"last_name" => 'Ghosh',
"gender" => 'male',
"phone"=> "<Phone-No>"
]
]);
// third link the bank account with the stripe account
$bankAccount = \Stripe\Account::createExternalAccount(
$stripeAccount->id,['external_account' => $bankToken->id]
);
// Fourth stripe account update for tos acceptance
\Stripe\Account::update(
$stripeAccount->id,[
'tos_acceptance' => [
'date' => time(),
'ip' => $_SERVER['REMOTE_ADDR'] // Assumes you're not using a proxy
],
]
);
$response = ["bankToken"=>$bankToken->id,"stripeAccount"=>$stripeAccount->id,"bankAccount"=>$bankAccount->id];
dd($response);
} catch (\Exception $e) {
dd($e->jsonBody['error']['message']);
}
I'm using the Paypal API to create a subscription system where there are two types of subscriptions
Monthly subscription (5dlls)
Annual subscription (50dlls)
I currently have the following code:
For setting the checkout:
public function do_purchase($type){
$this->load->library('paypal');
$requestParams = array(
'RETURNURL' => site_url('restaurant/get_purchase_details'),
'CANCELURL' => site_url('restaurant/afiliaturestaurante')
);
$orderParams = array(
'L_BILLINGTYPE0' => 'RecurringPayments',
'L_BILLINGAGREEMENTDESCRIPTION0' => 'Monthly',
'AMT' => 0
);
$paypal = new Paypal();
$response = $paypal -> request('SetExpressCheckout',$requestParams + $orderParams);
if(is_array($response) && $response['ACK'] == 'Success') { //Request successful
$token = $response['TOKEN'];
header( 'Location: https://www.sandbox.paypal.com/webscr?cmd=_express-checkout&token=' . urlencode($token) );
}
}
For creating the recurring Paypal profile:
public function get_purchase_details(){
if( isset($_GET['token']) && !empty($_GET['token']) ) { // Token parameter exists
// Get checkout details, including buyer information.
// We can save it for future reference or cross-check with the data we have
$this->load->library('paypal');
$paypal = new Paypal();
$checkoutDetails = $paypal -> request('GetExpressCheckoutDetails', array('TOKEN' => $_GET['token']));
// Complete the checkout transaction
$requestParams = array(
'TOKEN' => $_GET['token'],
'PAYERID' => $checkoutDetails['PAYERID'],
'PROFILESTARTDATE' => '2014-03-7T05:38:48Z',
'DESC' => 'Monthly',
'BILLINGPERIOD' => 'Month',
'BILLINGFREQUENCY' => '1',
'AMT' => '5',
'CURRENCYCODE' => 'USD',
'COUNTRYCODE' => 'US',
'MAXFAILEDPAYMENTS' => '3',
);
$response = $paypal -> request('CreateRecurringPaymentsProfile',$requestParams);
if( is_array($response) && $response['ACK'] == 'Success') { // Payment successful
// We'll fetch the transaction ID for internal bookkeeping
$profileID = $response['PROFILEID'];
}
}
}
I need to use $type variable on get_purchase_details for setting the amount of the profile, how can I pass the variable through Paypal so I can user on the other function? I'm using a Paypal library for creating the cURL requests.
Thanks in advance
You could just set the value of $type in a session variable, and that would be available upon return from PayPal.
Alternatively, you could pass your $type value in the CUSTOM parameter of SetExpressCheckout and that way it'll be returned in the GetExpressCheckoutDetails response.
I'm trying to setup recurring payments in paypal with PHP. But the problem that I'm having is that I don't know if I'm doing the right thing. I have this class which makes the request to the Paypal API:
<?php
class Paypal {
protected $_errors = array();
protected $_credentials = array(
'USER' => 'my-user-id',
'PWD' => 'my-pass',
'SIGNATURE' => 'my-signature',
);
protected $_endPoint = 'https://api-3t.sandbox.paypal.com/nvp';
protected $_version = '74.0';
public function request($method,$params = array()) {
$this -> _errors = array();
if( empty($method) ) {
$this -> _errors = array('API method is missing');
return false;
}
$requestParams = array(
'METHOD' => $method,
'VERSION' => $this -> _version
) + $this -> _credentials;
$request = http_build_query($requestParams + $params);
$http_header = array(
'X-PAYPAL-SECURITY-USERID' => 'my-user-id',
'X-PAYPAL-SECURITY-PASSWORD' => 'my-pass',
'X-PAYPAL-SECURITY-SIGNATURE' => 'my-signature',
'X-PAYPAL-REQUEST-DATA-FORMAT' => 'JSON',
'X-PAYPAL-RESPONSE-DATA-FORMAT' => 'JSON'
);
$curlOptions = array (
CURLOPT_HTTPHEADER => $http_header,
CURLOPT_URL => $this -> _endPoint,
CURLOPT_VERBOSE => 1,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $request
);
$ch = curl_init();
curl_setopt_array($ch,$curlOptions);
$response = curl_exec($ch);
if (curl_errno($ch)) {
$this -> _errors = curl_error($ch);
curl_close($ch);
return false;
} else {
curl_close($ch);
$responseArray = array();
parse_str($response,$responseArray);
return $responseArray;
}
}
}
?>
Then I'm making the initial request like this:
session_start();
require_once('Paypal.php');
$paypal = new Paypal();
$amount = 1;
$requestParams = array(
'RETURNURL' => 'http://localhost/tester/paypal/new_test/test_done.php',
'CANCELURL' => 'http://localhost/tester/paypal/new_test/test_cancel.php',
'NOSHIPPING' => '1',
'ALLOWNOTE' => '1',
'L_BILLINGTYPE0' => 'RecurringPayments',
'L_BILLINGAGREEMENTDESCRIPTION0' => 'site donation'
);
$orderParams = array(
'PAYMENTREQUEST_0_AMT' => '1',
'PAYMENTREQUEST_0_CURRENCYCODE' => 'USD',
'PAYMENTREQUEST_0_ITEMAMT' => $amount
);
$item = array(
'L_PAYMENTREQUEST_0_NAME0' => 'site donation',
'L_PAYMENTREQUEST_0_DESC0' => 'site donation',
'L_PAYMENTREQUEST_0_AMT0' => $amount,
'L_PAYMENTREQUEST_0_QTY0' => '1'
);
$response = $paypal->request('SetExpressCheckout', $requestParams + $orderParams + $item);
$sandbox_location = 'https://www.sandbox.paypal.com/webscr?cmd=_express-checkout&token=';
if(is_array($response) && $response['ACK'] == 'Success'){
$token = $response['TOKEN'];
$_SESSION['token'] = $token;
header('Location: ' . $sandbox_location . urlencode($token));
}
?>
As you can see I'm using the SetExpressCheckout API method to get the token that I need and store it in a session so that I can use it later with the request for CreateRecurringPaymentsProfile.
I'm currently redirected to a page similar to this:
Once the user is done logging in with paypal and confirming the amount it redirects to the success page that I've specified which contains this code:
session_start();
require_once('Paypal.php');
$amount = 1;
$paypal = new Paypal();
$token_param = array('TOKEN' => $_SESSION['token']);
$current_date = date('Y-m-d');
$recurring_payment_params = array(
'PROFILESTARTDATE' => gmdate('Y-m-d H:i:s', strtotime($current_date . ' + 1 months')),
'DESC' => 'site donation',
'BILLINGPERIOD' => 'Month',
'BILLINGFREQUENCY' => '1',
'TOTALBILLINGCYCLES' => '0',
'AMT' => $amount
);
$recurringpayment_response = $paypal->request('CreateRecurringPaymentsProfile', $recurring_payment_params + $token_param);
This works, I've verified in the sandbox account that the recurring payment profile was created and that the next billing due is next month. But the problem is that its not really visible in the paypal interface (the screenshot earlier) that they're paying for a subscription. Perhaps I'm getting the redirect url wrong? (https://www.sandbox.paypal.com/webscr?cmd=_express-checkout&token=) or do I have to add additional arguments to the SetExpressCheckout method? Please help.
You're only showing the login screen. After you login you'll see information about the subscription and the button will see "Agree and Pay" or "Agree and Continue" (depending on your useraction value in the return URL) instead of just "Pay" or "Continue".