[英]Yii2 paypal payment integration
I am using this https:\/\/www.yiiframework.com\/extension\/bitcko\/yii2-bitcko-paypal-api#usage<\/a> With yii2 to enable payments my code looks like this.我正在使用这个
https:\/\/www.yiiframework.com\/extension\/bitcko\/yii2-bitcko-paypal-api#usage<\/a>使用 yii2 来启用付款,我的代码如下所示。
public function actionMakePayment(){
if(!Yii::$app->user->getIsGuest()){
// Setup order information array
$params = [
'order'=>[
'description'=>'Payment description',
'subtotal'=>45,
'shippingCost'=>0,
'total'=>45,
'currency'=>'USD',
]
];
// In case of payment success this will return the payment object that contains all information about the order
// In case of failure it will return Null
Yii::$app->PayPalRestApi->processPayment($params);
}else{
Yii::$app->response->redirect(Url::to(['site/signup'], true));
}
Update<\/strong>更新<\/strong>
Looks like the component class needs to be fully copied and edited before it can correctly override the
checkOut()<\/code> method as the property
$apiContext<\/code> accessed in the method is
private<\/code> rather than being
$protected<\/code> so either you copy that whole component and place it in you
frontend\/components<\/code> directory and change it accordingly and then use.
看起来组件类需要完全复制和编辑才能正确覆盖
checkOut()<\/code>方法,因为在该方法中访问的属性
$apiContext<\/code>是
private<\/code>的而不是
$protected<\/code>所以你要么复制整个组件并将其放入你
frontend\/components<\/code>目录并相应地更改它然后使用。
Above all that class is poorly designed and written too, it would be better if you use the following component that i have been using in my Yii2 projects.最重要的是,该类的设计和编写也很糟糕,如果您使用我在 Yii2 项目中一直使用的以下组件会更好。 I havent removed the extra code and have pasted the file as is in the answer.
我没有删除额外的代码并按照答案粘贴了文件。 you can remove\/comment the part related to the
BalanceHistory<\/code>
TransactionHistory<\/code> and the email part.
您可以删除\/评论与
BalanceHistory<\/code>
TransactionHistory<\/code>和电子邮件部分相关的部分。
you need to install paypal checkout sdk via composer or add below in your
composer.json<\/code>
您需要通过 composer 安装 paypal checkout sdk 或在您的
composer.json<\/code>中添加以下内容
"paypal\/paypal-checkout-sdk": "1.0.1"<\/code>
Paypal Component贝宝组件
<?php
namespace frontend\components;
use Yii;
use common\models\{
User,
BalanceHistory,
TransactionHistory
};
use yii\base\Component;
use common\components\Helper;
use PayPalCheckoutSdk\Core\{
PayPalHttpClient,
SandboxEnvironment,
ProductionEnvironment
};
use PayPalCheckoutSdk\Orders\{
OrdersGetRequest,
OrdersCreateRequest,
OrdersCaptureRequest
};
class Paypal extends Component
{
/**
* The Pyapal Client Id
*
* @var mixed
*/
public $clientId;
/**
* The Paypal client Secret
*
* @var mixed
*/
public $clientSecret;
/**
* API context object
*
* @var mixed
*/
private $httpClient; // paypal's http client
/**
* @var mixed
*/
private $user_id;
/**
* Override Yii's object init()
*
* @return null
*/
public function init()
{
$this->httpClient = new PayPalHttpClient(
Yii::$app->params['paypal']['mode'] == 'sandbox' ?
new SandboxEnvironment($this->clientId, $this->clientSecret) :
new ProductionEnvironment($this->clientId, $this->clientSecret)
);
$this->user_id = Yii::$app->user->id;
Yii::info("User: {$this->user_id} Init PayPal", 'paypal');
}
/**
* Returns the context object
*
* @return object
*/
public function getClient()
{
return $this->httpClient;
}
/**
* Set the payment methods and other objects necessary for making the payment
*
* @param decimal $price the amount to be charged
*
* @return string $approvalUrl
*/
public function createOrder($price)
{
//create order request
$request = new OrdersCreateRequest();
$request->prefer('return=representation');
setlocale(LC_MONETARY, 'en_US.UTF-8');
$price = sprintf('%01.2f', $price);
Yii::info("User: {$this->user_id} Setting payment for amount: {$price}", 'paypal');
//build the request body
$requestBody = [
'intent' => 'CAPTURE',
'purchase_units' =>
[
0 =>
[
'amount' =>
[
'currency_code' => 'USD',
'value' => $price,
],
],
],
'application_context' => [
'shipping_preference' => 'NO_SHIPPING'
]
];
$request->body = $requestBody;
//call PayPal to set up a transaction
$client = $this->getClient();
$response = $client->execute($request);
return json_encode($response->result, JSON_PRETTY_PRINT);
}
/**
* @param $orderId
*/
public function getOrder($orderId)
{
// 3. Call PayPal to get the transaction details
$request = new OrdersGetRequest($orderId);
$client = $this->getClient();
$response = $client->execute($request);
return json_encode($response->result, JSON_PRETTY_PRINT);
}
/**
* Retrieves Order Capture Details for the given order ID
*
* @param string $orderId the payment id of the transaction
*
* @return mixed
*/
public function captureOrder($orderId)
{
$request = new OrdersCaptureRequest($orderId);
//Call PayPal to capture an authorization
$client = $this->getClient();
$transaction = Yii::$app->db->beginTransaction();
try {
$response = $client->execute($request);
//get payment variables for email
$paymentId = $response->result->id;
$paymentStatus = $response->result->status;
$paypalTransaction = $response->result->purchase_units[0]->payments->captures[0];
$payedAmount = $paypalTransaction->amount->value;
$txnId = $paypalTransaction->id;
$userId = $this->user_id;
//get the user
$model = User::findOne($userId);
$profile = $model->businessProfile;
$prevBalance = $profile->balance;
if ($paymentStatus == 'COMPLETED') {
Yii::info("User: {$userId} payment amount:{$payedAmount} approved updating balance.", 'paypal');
//update balance
$newBalance = $profile->updateBalance($payedAmount);
Yii::info("User: {$userId} balance updated.", 'paypal');
$data = [
'amount' => $payedAmount,
'type' => TransactionHistory::BALANCE_ADDED,
'description' => "Funds added to account",
'user' => [
'id' => $userId,
'balance' => $newBalance,
],
];
Yii::info("User: {$userId} adding transaction history.", 'paypal');
TransactionHistory::add($data);
//update subscription status if required
if ($profile->subscription_status !== 'active') {
$profile->updateStatus('active');
}
Yii::info("User: {$userId} adding balance history:{$payedAmount}.", 'paypal');
//send the success email to the user and admin
$this->sendNotification($model, $response->result);
//set session flash with success
Yii::$app->session->setFlash(
'success',
'Your Payment is processed and you will receive an email with the details shortly'
);
} else {
Yii::warning("User: {$userId} payment amount:{$payedAmount} NOT approved.", 'paypal');
//send the error email to the user and admin
$this->sendNotification($model, $response->result, 'error');
//set session flash with error
Yii::$app->session->setFlash(
'danger',
'Your Payment was not approved, an email has been sent with the details.'
);
}
//update balance history
BalanceHistory::add(
$profile->user_id,
$prevBalance,
$payedAmount,
$paymentId,
$paymentStatus,
$txnId,
$response
);
//commit the transaction
$transaction->commit();
Yii::info(
"User: {$userId} payment Success prevBalance: {$prevBalance} payedAmount:{$payedAmount}.",
'paypal'
);
return json_encode($response->result, JSON_PRETTY_PRINT);
} catch (\Exception $e) {
//roll back the transaction
$transaction->rollBack();
Yii::error("ERROR EXCEPTION", 'paypal');
Yii::error($e->getMessage(), 'paypal');
Yii::error($e->getTraceAsString(), 'paypal');
//send error email to the developers
Helper::sendExceptionEmail(
"TC : Exception on PayPal Balance",
$e->getMessage(),
$e->getTraceAsString()
);
//set session flash with error
Yii::$app->session->setFlash('danger', $e->getMessage());
}
}
/**
* Sends Success Email for the transaction
*
* @param \common\models\User $model the user model object
* @param $response the paypal Order Capture object
* @param string $type the type of the notification to be sent
*
* @return null
*/
public function sendNotification(
\common\models\User $model,
$response,
$type = 'success'
) {
Yii::info("User: {$this->user_id} Sending notifications type:{$type}", 'paypal');
$paymentId = $response->id;
$paymentStatus = $response->status;
$paypalTransaction = $response->purchase_units[0]->payments->captures[0];
$payedAmount = $paypalTransaction->amount->value;
//payment creation time
$paymentCreateTime = new \DateTime(
$paypalTransaction->create_time,
new \DateTimeZone('UTC')
);
//payment update time
$paymentUpdateTime = new \DateTime(
$paypalTransaction->update_time,
new \DateTimeZone('UTC')
);
//payer/billing info for email
$payerInfo = $response->payer;
$payerEmail = $payerInfo->email_address;
$payerFirstName = $payerInfo->name->given_name;
$payerLastName = $payerInfo->name->surname;
$billingInfo = [
'billing_info' => [
'email' => $payerEmail,
'full_name' => "$payerFirstName $payerLastName",
],
];
if (property_exists($response->purchase_units[0], 'shipping')) {
$payerAddress = property_exists($response->purchase_units[0]->shipping->address, 'address_line_1');
$isStateAvailable = property_exists($response->purchase_units[0]->shipping->address, 'admin_area_1');
$isPostCodeAvailable = property_exists($response->purchase_units[0]->shipping->address, 'postal_code');
$iscountryCodeAvailable = property_exists($response->purchase_units[0]->shipping->address, 'country_code');
//@codingStandardsIgnoreStart
$payerState = $isStateAvailable ? $response->purchase_units[0]->shipping->address->admin_area_1 : 'NA';
$payerPostalCode = $isPostCodeAvailable ? $response->purchase_units[0]->shipping->address->postal_code : 'NA';
$payerCountryCode = $iscountryCodeAvailable ? $response->purchase_units[0]->shipping->address->country_code : 'NA';
//@codingStandardsIgnoreEnd
$billingInfo['billing_info'] = array_merge(
$billingInfo['billing_info'],
[
'address' => $payerAddress,
'state' => $payerState,
'country' => $payerCountryCode,
'post_code' => $payerPostalCode,
]
);
}
//email params
$data = [
'user' => [
'email' => $model->email,
'name' => $model->username,
],
'payment_id' => $paymentId,
'amount' => $payedAmount,
'status' => $paymentStatus,
'create_time_utc' => $paymentCreateTime,
'update_time_utc' => $paymentUpdateTime,
];
$data = array_merge($data, $billingInfo);
//check the notification email type and set params accordingly
if ($type == 'success') {
$txnId = $paypalTransaction->id;
$data['txn_id'] = $txnId;
$subject = Yii::$app->id . ': Your Account has been recharged.';
$view = '@frontend/views/user/mail/payment-complete';
} else {
$subject = Yii::$app->id . ': Transaction failed.';
$view = '@frontend/views/user/mail/payment-failed';
}
Yii::info("User: {$this->user_id} Sending email to user:{$model->email} type: {$type}", 'paypal');
//send email to user
$model->sendEmail($subject, $view, $data, $model->email);
//send notification to admin for Payment Received
$data['user']['email'] = Yii::$app->params['adminEmail'];
$subject = ($type == 'success') ?
Yii::$app->id . ': New Transaction in Account.' :
Yii::$app->user->id . ': A Transaction Failed for the user.';
Yii::info(
"User: {$this->user_id} Sending email to admin " . Yii::$app->params['adminEmail'] . " type: {$type}",
'paypal'
);
//send admin email
$model->sendEmail($subject, $view, $data, Yii::$app->params['adminEmail']);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.