Chủ Nhật, 17 tháng 10, 2021

Tích hợp VNPAY (laravel, php)

 

Tạo VnpayController và 2 hàm create và return.

Function create sẽ cấu hình để gửi dữ liệu sang Vnpay:

/**
* Hàm gửi thông tin thanh toán đến VNpay
*/
public function create(Request $request)
{
session(['booking_code' => $request->order_id]);
// session(['url_prev' => url()->previous()]);

// Các mã config đã để ở file .env rồi
$vnp_TmnCode = env('VNP_TMN_CODE'); //Mã website tại VNPAY; "XSY4HIVO"
$vnp_HashSecret = env('VNP_HASH_SECRET'); //Chuỗi bí mật; "MXOGEMDPHWSBWPCPERSLIKFXFLNRLQIR"
$vnp_Url = env('VNP_URL'); //"https://sandbox.vnpayment.vn/paymentv2/vpcpay.html"
$vnp_Returnurl = env('VNP_RETURN_URL'); //"http://127.0.0.1:8000/return-vnpay"

$vnp_TxnRef = $request->order_id; //Mã đơn hàng. Trong thực tế Merchant cần insert đơn hàng vào DB và gửi mã này sang VNPAY
$vnp_OrderInfo = $request->order_desc; //Thông tin mô tả nội dung thanh toán (Tiếng Việt, không dấu).
$vnp_OrderType = $request->order_type; //Loại thanh toán; 'billpayment'
$vnp_Amount = $request->amount * 100; //Số tiền thanh toán. VNPAY phản hồi số tiền nhân thêm 100 lần.
$vnp_Locale = $request->language;
$vnp_BankCode = $request->bank_code; //Mã ngân hàng
$vnp_IpAddr = request()->ip();

//Add Params of 2.0.1 Version
$vnp_ExpireDate = $request->txtexpire;

$inputData = array(
"vnp_Version" => "2.1.0",
"vnp_TmnCode" => $vnp_TmnCode,
"vnp_Amount" => $vnp_Amount,
"vnp_Command" => "pay",
"vnp_CreateDate" => date('YmdHis'),
"vnp_CurrCode" => "VND",
"vnp_IpAddr" => $vnp_IpAddr,
"vnp_Locale" => $vnp_Locale,
"vnp_OrderInfo" => $vnp_OrderInfo,
"vnp_OrderType" => $vnp_OrderType,
"vnp_ReturnUrl" => $vnp_Returnurl,
"vnp_TxnRef" => $vnp_TxnRef,
//Add params version 2.0.1
"vnp_ExpireDate" => $vnp_ExpireDate,
);

if (isset($vnp_BankCode) && $vnp_BankCode != "") {
$inputData['vnp_BankCode'] = $vnp_BankCode;
}
if (isset($vnp_Bill_State) && $vnp_Bill_State != "") {
$inputData['vnp_Bill_State'] = $vnp_Bill_State;
}

ksort($inputData);
$query = "";
$i = 0;
$hashdata = "";
foreach ($inputData as $key => $value) {
if ($i == 1) {
$hashdata .= '&' . urlencode($key) . "=" . urlencode($value);
} else {
$hashdata .= urlencode($key) . "=" . urlencode($value);
$i = 1;
}
$query .= urlencode($key) . "=" . urlencode($value) . '&';
}

$vnp_Url = $vnp_Url . "?" . $query;
if (isset($vnp_HashSecret)) {
$vnpSecureHash = hash_hmac('sha512', $hashdata, $vnp_HashSecret);
$vnp_Url .= 'vnp_SecureHash=' . $vnpSecureHash;
}
return redirect($vnp_Url);
}


Function return sẽ lấy dữ liệu được trả về qua url tại $vnp_Returnurl, sau đó xử lý và lưy vào DB:

/**
* Hàm trả lại kết quả (lấy kết quả tại link trong $vnp_Returnurl ở hàm create).
*/
public function return(Request $request)
{
$vnp_HashSecret = env('VNP_HASH_SECRET'); //Chuỗi bí mật
// $url = session('url_prev', '/');
// Lay ma hash VnPay tra ve
$vnp_SecureHash = $request->query('vnp_SecureHash');
// Tao ma hash tu cac du lieu do VnPay tra ve
$inputData = array();
foreach ($request->query() as $key => $value) {
if (substr($key, 0, 4) == "vnp_") {
$inputData[$key] = $value;
}
}
unset($inputData['vnp_SecureHash']);
ksort($inputData);
$i = 0;
$hashData = "";
foreach ($inputData as $key => $value) {
if ($i == 1) {
$hashData = $hashData . '&' . urlencode($key) . "=" . urlencode($value);
} else {
$hashData = $hashData . urlencode($key) . "=" . urlencode($value);
$i = 1;
}
}
$secureHash = hash_hmac('sha512', $hashData, $vnp_HashSecret);

// So sánh 2 mã hash vừa tạo bằng dữ liệu trả về và mã hashcuar VnPay
if ($secureHash == $vnp_SecureHash) {
// Check ResponseCode và update lại vào DB
if ($request->query('vnp_ResponseCode') == "00") {
$this->bookingRepository->successfulOnlinePayment(session('booking_code'));
$data = ['msg' => __('Giao dịch thành công.')];
} else if ($request->query('vnp_ResponseCode') == "24") {
$this->bookingRepository->failedOnlinePayment(session('booking_code'), 2);
$data = ['msg' => __('Giao dịch thất bại! Booking đã bị hủy.')];
} else {
$this->bookingRepository->failedOnlinePayment(session('booking_code'), 3);
$data = ['msg' => __('Giao dịch thất bại! Booking đã bị lỗi')];
}
} else {
$data = ['msg' => __('Chữ ký không hợp lệ.')];
}
// session()->forget('url_prev');

return view('frontend.booking.return', compact('data'));
}


Có thể tạo 1 view, sau khi lưu thông tin order vào DB rồi thì sẽ hiện vieư để chọn ngân hàng, thông tin thanh toán:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<meta name="description" content="">
<meta name="author" content="">
<title>Tạo mới đơn hàng</title>
<!-- Bootstrap core CSS -->
<link href="./vnpay_php/assets/bootstrap.min.css" rel="stylesheet" />
<!-- Custom styles for this template -->
<link href="./vnpay_php/assets/jumbotron-narrow.css" rel="stylesheet">
<script src="./vnpay_php/assets/jquery-1.11.3.min.js"></script>
</head>

<body>

<div class="container">
<div class="header clearfix">
<h3 class="text-muted">VNPAY DEMO</h3>
</div>
<h3>Tạo mới đơn hàng</h3>
<div class="table-responsive">
<form action="{{ route('vnpay') }}" id="create_form" method="post">
@csrf
<div class="form-group">
<label for="language">Loại hàng hóa </label>
<select name="order_type" id="order_type" class="form-control">
<option value="topup" disabled>Nạp tiền điện thoại</option>
<option value="billpayment">Thanh toán hóa đơn</option>
<option value="fashion" disabled>Thời trang</option>
<option value="other" disabled>Khác - Xem thêm tại VNPAY</option>
</select>
</div>
<div class="form-group">
<label for="order_id">Mã hóa đơn</label>
<input class="form-control" id="order_id" name="order_id" type="text" value="{{ $data['id'] }}"
readonly />
</div>
<div class="form-group">
<label for="amount">Số tiền</label>
<input class="form-control" id="amount" name="amount" type="number"
value="{{ $data['total_price'] }}" readonly />
</div>
<div class="form-group">
<label for="order_desc">Nội dung thanh toán</label>
<textarea class="form-control" cols="20" id="order_desc" name="order_desc"
rows="2">Thanh Toan Booking</textarea>
</div>
<div class="form-group">
<label for="bank_code">Ngân hàng</label>
<select name="bank_code" id="bank_code" class="form-control">
<option value="">Không chọn</option>
<option value="NCB"> Ngan hang NCB</option>
<option value="AGRIBANK"> Ngan hang Agribank</option>
<option value="SCB"> Ngan hang SCB</option>
<option value="SACOMBANK">Ngan hang SacomBank</option>
<option value="EXIMBANK"> Ngan hang EximBank</option>
<option value="MSBANK"> Ngan hang MSBANK</option>
<option value="NAMABANK"> Ngan hang NamABank</option>
<option value="VNMART"> Vi dien tu VnMart</option>
<option value="VIETINBANK">Ngan hang Vietinbank</option>
<option value="VIETCOMBANK"> Ngan hang VCB</option>
<option value="HDBANK">Ngan hang HDBank</option>
<option value="DONGABANK"> Ngan hang Dong A</option>
<option value="TPBANK"> Ngân hàng TPBank</option>
<option value="OJB"> Ngân hàng OceanBank</option>
<option value="BIDV"> Ngân hàng BIDV</option>
<option value="TECHCOMBANK"> Ngân hàng Techcombank</option>
<option value="VPBANK"> Ngan hang VPBank</option>
<option value="MBBANK"> Ngan hang MBBank</option>
<option value="ACB"> Ngan hang ACB</option>
<option value="OCB"> Ngan hang OCB</option>
<option value="IVB"> Ngan hang IVB</option>
<option value="VISA"> Thanh toan qua VISA/MASTER</option>
</select>
</div>
<div class="form-group">
<label for="language">Ngôn ngữ</label>
<select name="language" id="language" class="form-control">
<option value="vn">Tiếng Việt</option>
<option value="en">English</option>
</select>
</div>
<div class="form-group">
<label>Thời hạn thanh toán</label>
<input class="form-control" type="text"
value="{{ date('Y-m-d H:i:s',strtotime('+15 minutes',strtotime(date('YmdHis')))) }}" disabled />
<input type="hidden" name="txtexpire"
value="{{ date('YmdHis',strtotime('+15 minutes',strtotime(date('YmdHis')))) }}">
</div>
{{-- <div class="form-group">
<h3>Thông tin hóa đơn (Billing)</h3>
</div>
<div class="form-group">
<label>Họ tên (*)</label>
<input class="form-control" id="txt_billing_fullname" name="txt_billing_fullname" type="text"
value="NGUYEN VAN XO" />
</div>
<div class="form-group">
<label>Email (*)</label>
<input class="form-control" id="txt_billing_email" name="txt_billing_email" type="text"
value="xonv@vnpay.vn" />
</div>
<div class="form-group">
<label>Số điện thoại (*)</label>
<input class="form-control" id="txt_billing_mobile" name="txt_billing_mobile" type="text"
value="0934998386" />
</div>
<div class="form-group">
<label>Địa chỉ (*)</label>
<input class="form-control" id="txt_billing_addr1" name="txt_billing_addr1" type="text"
value="22 Lang Ha" />
</div>
<div class="form-group">
<label>Mã bưu điện (*)</label>
<input class="form-control" id="txt_postalcode" name="txt_postalcode" type="text" value="100000" />
</div>
<div class="form-group">
<label>Tỉnh/TP (*)</label>
<input class="form-control" id="txt_bill_city" name="txt_bill_city" type="text" value="Hà Nội" />
</div>
<div class="form-group">
<label>Bang (Áp dụng cho US,CA)</label>
<input class="form-control" id="txt_bill_state" name="txt_bill_state" type="text" value="" />
</div>
<div class="form-group">
<label>Quốc gia (*)</label>
<input class="form-control" id="txt_bill_country" name="txt_bill_country" type="text" value="VN" />
</div> --}}
{{-- <div class="form-group">
<h3>Thông tin giao hàng (Shipping)</h3>
</div>
<div class="form-group">
<label>Họ tên (*)</label>
<input class="form-control" id="txt_ship_fullname" name="txt_ship_fullname" type="text"
value="Nguyễn Thế Vinh" />
</div>
<div class="form-group">
<label>Email (*)</label>
<input class="form-control" id="txt_ship_email" name="txt_ship_email" type="text"
value="vinhnt@vnpay.vn" />
</div>
<div class="form-group">
<label>Số điện thoại (*)</label>
<input class="form-control" id="txt_ship_mobile" name="txt_ship_mobile" type="text"
value="0123456789" />
</div>
<div class="form-group">
<label>Địa chỉ (*)</label>
<input class="form-control" id="txt_ship_addr1" name="txt_ship_addr1" type="text"
value="Phòng 315, Công ty VNPAY, Tòa nhà TĐL, 22 Láng Hạ, Đống Đa, Hà Nội" />
</div>
<div class="form-group">
<label>Mã bưu điện (*)</label>
<input class="form-control" id="txt_ship_postalcode" name="txt_ship_postalcode" type="text"
value="1000000" />
</div>
<div class="form-group">
<label>Tỉnh/TP (*)</label>
<input class="form-control" id="txt_ship_city" name="txt_ship_city" type="text" value="Hà Nội" />
</div>
<div class="form-group">
<label>Bang (Áp dụng cho US,CA)</label>
<input class="form-control" id="txt_ship_state" name="txt_ship_state" type="text" value="" />
</div>
<div class="form-group">
<label>Quốc gia (*)</label>
<input class="form-control" id="txt_ship_country" name="txt_ship_country" type="text" value="VN" />
</div>
<div class="form-group">
<h3>Thông tin gửi Hóa đơn điện tử (Invoice)</h3>
</div>
<div class="form-group">
<label>Tên khách hàng</label>
<input class="form-control" id="txt_inv_customer" name="txt_inv_customer" type="text"
value="Lê Văn Phổ" />
</div>
<div class="form-group">
<label>Công ty</label>
<input class="form-control" id="txt_inv_company" name="txt_inv_company" type="text"
value="Công ty Cổ phần giải pháp Thanh toán Việt Nam" />
</div>
<div class="form-group">
<label>Địa chỉ</label>
<input class="form-control" id="txt_inv_addr1" name="txt_inv_addr1" type="text"
value="22 Láng Hạ, Phường Láng Hạ, Quận Đống Đa, TP Hà Nội" />
</div>
<div class="form-group">
<label>Mã số thuế</label>
<input class="form-control" id="txt_inv_taxcode" name="txt_inv_taxcode" type="text"
value="0102182292" />
</div>
<div class="form-group">
<label>Loại hóa đơn</label>
<select name="cbo_inv_type" id="cbo_inv_type" class="form-control">
<option value="I">Cá Nhân</option>
<option value="O">Công ty/Tổ chức</option>
</select>
</div>
<div class="form-group">
<label>Email</label>
<input class="form-control" id="txt_inv_email" name="txt_inv_email" type="text"
value="pholv@vnpay.vn" />
</div>
<div class="form-group">
<label>Điện thoại</label>
<input class="form-control" id="txt_inv_mobile" name="txt_inv_mobile" type="text"
value="02437764668" />
</div> --}}
<button type="submit" class="btn btn-primary" id="btnPopup">Thanh toán</button>
{{-- <button type="submit" name="redirect" id="redirect" class="btn btn-default">Thanh toán
Redirect</button> --}}
</form>
</div>
<p>
&nbsp;
</p>
<footer class="footer">
<p>&copy; VNPAY
<?php echo date('Y')?>
</p>
</footer>
</div>

</body>

</html>

View này sẽ post đến hàm create trong VnpayController.

Và có thể tạo 1 view hiển kết quả sau khi xử lí trong hàm return:

@extends('frontend.master')

@push('title', 'Booking')

@section('content')
<div>
<h4>{{ $data['msg'] }}</h4>
<div>
<a href="{{ url('/') }}">Đặt Tour khác</a>
<a href="#">Xem các đơn booking</a>
</div>
</div>
@endsection


Có thể đặt biến cấu hình tại class VnpayController, trong function hoặc trong file .env:

VNP_TMN_CODE=XSY4HIVO
VNP_HASH_SECRET=MXOGEMDPHWSBWPCPERSLIKFXFLNRLxxx
VNP_URL=https://sandbox.vnpayment.vn/paymentv2/vpcpay.html
VNP_RETURN_URL=http://127.0.0.1:8000/return-vnpay

Mã cấu hình sẽ có khi đăng ký tại https://sandbox.vnpayment.vn/devreg



Tham khảo: VibloVNPAY

Không có nhận xét nào:

Đăng nhận xét