() translation by (you can also view the original English article)
Nếu bạn đã theo dõi loạt bài này, thì bạn sẽ quen thuộc với cấu trúc file mà chúng tôi đã thiết lập cho phương thức thanh toán tùy chỉnh của chúng tôi ở bên dưới. Nếu bạn chưa xem qua các phần trước của loạt bài này, tôi khuyên bạn nên đọc chúng trước khi tiếp tục.
Chúng ta cũng sẽ sử dụng kiểu thiết lập tệp tương tự cho phần front-end.
Thiết lập bộ controller
Tiếp tục tạo tập tin bộ điều khiển tại catalog/controller/payment/custom.php. Dán các nội dung sau vào file controller vừa tạo ra custom.php.
1 |
<?php
|
2 |
class ControllerPaymentCustom extends Controller { |
3 |
protected function index() { |
4 |
$this->language->load('payment/custom'); |
5 |
$this->data['button_confirm'] = $this->language->get('button_confirm'); |
6 |
$this->data['action'] = 'https://yourpaymentgatewayurl'; |
7 |
|
8 |
$this->load->model('checkout/order'); |
9 |
$order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']); |
10 |
|
11 |
if ($order_info) { |
12 |
$this->data['text_config_one'] = trim($this->config->get('text_config_one')); |
13 |
$this->data['text_config_two'] = trim($this->config->get('text_config_two')); |
14 |
$this->data['orderid'] = date('His') . $this->session->data['order_id']; |
15 |
$this->data['callbackurl'] = $this->url->link('payment/custom/callback'); |
16 |
$this->data['orderdate'] = date('YmdHis'); |
17 |
$this->data['currency'] = $order_info['currency_code']; |
18 |
$this->data['orderamount'] = $this->currency->format($order_info['total'], $this->data['currency'] , false, false); |
19 |
$this->data['billemail'] = $order_info['email']; |
20 |
$this->data['billphone'] = html_entity_decode($order_info['telephone'], ENT_QUOTES, 'UTF-8'); |
21 |
$this->data['billaddress'] = html_entity_decode($order_info['payment_address_1'], ENT_QUOTES, 'UTF-8'); |
22 |
$this->data['billcountry'] = html_entity_decode($order_info['payment_iso_code_2'], ENT_QUOTES, 'UTF-8'); |
23 |
$this->data['billprovince'] = html_entity_decode($order_info['payment_zone'], ENT_QUOTES, 'UTF-8');; |
24 |
$this->data['billcity'] = html_entity_decode($order_info['payment_city'], ENT_QUOTES, 'UTF-8'); |
25 |
$this->data['billpost'] = html_entity_decode($order_info['payment_postcode'], ENT_QUOTES, 'UTF-8'); |
26 |
$this->data['deliveryname'] = html_entity_decode($order_info['shipping_firstname'] . $order_info['shipping_lastname'], ENT_QUOTES, 'UTF-8'); |
27 |
$this->data['deliveryaddress'] = html_entity_decode($order_info['shipping_address_1'], ENT_QUOTES, 'UTF-8'); |
28 |
$this->data['deliverycity'] = html_entity_decode($order_info['shipping_city'], ENT_QUOTES, 'UTF-8'); |
29 |
$this->data['deliverycountry'] = html_entity_decode($order_info['shipping_iso_code_2'], ENT_QUOTES, 'UTF-8'); |
30 |
$this->data['deliveryprovince'] = html_entity_decode($order_info['shipping_zone'], ENT_QUOTES, 'UTF-8'); |
31 |
$this->data['deliveryemail'] = $order_info['email']; |
32 |
$this->data['deliveryphone'] = html_entity_decode($order_info['telephone'], ENT_QUOTES, 'UTF-8'); |
33 |
$this->data['deliverypost'] = html_entity_decode($order_info['shipping_postcode'], ENT_QUOTES, 'UTF-8'); |
34 |
|
35 |
if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/payment/custom.tpl')){ |
36 |
$this->template = $this->config->get('config_template') . '/template/payment/custom.tpl'; |
37 |
} else { |
38 |
$this->template = 'default/template/payment/custom.tpl'; |
39 |
}
|
40 |
|
41 |
$this->render(); |
42 |
}
|
43 |
}
|
44 |
|
45 |
public function callback() { |
46 |
if (isset($this->request->post['orderid'])) { |
47 |
$order_id = trim(substr(($this->request->post['orderid']), 6)); |
48 |
} else { |
49 |
die('Illegal Access'); |
50 |
}
|
51 |
|
52 |
$this->load->model('checkout/order'); |
53 |
$order_info = $this->model_checkout_order->getOrder($order_id); |
54 |
|
55 |
if ($order_info) { |
56 |
$data = array_merge($this->request->post,$this->request->get); |
57 |
|
58 |
//payment was made successfully
|
59 |
if ($data['status'] == 'Y' || $data['status'] == 'y') { |
60 |
// update the order status accordingly
|
61 |
}
|
62 |
}
|
63 |
}
|
64 |
}
|
65 |
?>
|
Như bạn có thể thấy, có hai phương thức khác nhau. Phương thức index sẽ chịu trách nhiệm thiết lập dữ liệu khi biểu mẫu được gửi đến cổng thanh toán của bên thứ ba và phương thức callback được dùng để xử lý dữ liệu phản hồi từ cổng thanh toán. Bạn có thể xác định nhiều phương thức hơn nếu cổng thanh toán của bạn yêu cầu. Trong ví dụ này, chúng tôi đã duy trì quy trình đơn giản nhất có thể.
Hãy xem chi tiết từng phần. Chúng ta sẽ bắt đầu với phương thức index.
Đầu tiên, chúng tôi đã tải file ngôn ngữ và đặt giá trị của nút Confirm. Chúng tôi cũng đã thiết lập thuộc tính action sẽ được form gửi thanh toán sử dụng. Bạn nên thay đổi thuộc tính này tuỳ vào cổng thanh toán của bạn.
1 |
$this->language->load('payment/custom'); |
2 |
$this->data['button_confirm'] = $this->language->get('button_confirm'); |
3 |
$this->data['action'] = 'https://yourpaymentgatewayurl'; |
Tiếp theo, chúng tôi đã tải thông tin đơn đặt hàng từ phiên hoạt động của người dùng.
1 |
$this->load->model('checkout/order'); |
2 |
$order_info = $this->model_checkout_order->getOrder($this->session->data['order_id']); |
Nếu thông tin đặt hàng có sẵn, chúng tôi sẽ tiếp tục và thiết lập dữ liệu cho các biến hidden sẽ được sử dụng để gửi form tới URL cổng thanh toán. Nếu bạn tuân theo code chặt chẽ, bạn sẽ nhận thấy rằng chúng tôi cũng đã sử dụng các thông số tùy chỉnh của chúng tôi, text_config_one và text_config_two, chúng tôi đã thiết lập trong biểu mẫu cấu hình quản trị trong phần trước của loạt bài này.
Biến số quan trọng khác cần lưu ý ở đây là callbackurl, giữ URL được sử dụng bởi cổng thanh toán để chuyển hướng người dùng trở lại cửa hàng của chúng tôi sau quá trình thanh toán. Và vâng, hãy nhìn vào URL payment/custom/callback sẽ chỉ ra rằng nó sẽ gọi phương thức callback, như chúng ta sẽ thấy trong thời điểm này.
1 |
$this->data['text_config_one'] = trim($this->config->get('text_config_one')); |
2 |
$this->data['text_config_two'] = trim($this->config->get('text_config_two')); |
3 |
$this->data['orderid'] = date('His') . $this->session->data['order_id']; |
4 |
$this->data['callbackurl'] = $this->url->link('payment/custom/callback'); |
5 |
$this->data['orderdate'] = date('YmdHis'); |
6 |
$this->data['currency'] = $order_info['currency_code']; |
7 |
$this->data['orderamount'] = $this->currency->format($order_info['total'], $this->data['currency'] , false, false); |
8 |
$this->data['billemail'] = $order_info['email']; |
9 |
$this->data['billphone'] = html_entity_decode($order_info['telephone'], ENT_QUOTES, 'UTF-8'); |
10 |
$this->data['billaddress'] = html_entity_decode($order_info['payment_address_1'], ENT_QUOTES, 'UTF-8'); |
11 |
$this->data['billcountry'] = html_entity_decode($order_info['payment_iso_code_2'], ENT_QUOTES, 'UTF-8'); |
12 |
$this->data['billprovince'] = html_entity_decode($order_info['payment_zone'], ENT_QUOTES, 'UTF-8');; |
13 |
$this->data['billcity'] = html_entity_decode($order_info['payment_city'], ENT_QUOTES, 'UTF-8'); |
14 |
$this->data['billpost'] = html_entity_decode($order_info['payment_postcode'], ENT_QUOTES, 'UTF-8'); |
15 |
$this->data['deliveryname'] = html_entity_decode($order_info['shipping_firstname'] . $order_info['shipping_lastname'], ENT_QUOTES, 'UTF-8'); |
16 |
$this->data['deliveryaddress'] = html_entity_decode($order_info['shipping_address_1'], ENT_QUOTES, 'UTF-8'); |
17 |
$this->data['deliverycity'] = html_entity_decode($order_info['shipping_city'], ENT_QUOTES, 'UTF-8'); |
18 |
$this->data['deliverycountry'] = html_entity_decode($order_info['shipping_iso_code_2'], ENT_QUOTES, 'UTF-8'); |
19 |
$this->data['deliveryprovince'] = html_entity_decode($order_info['shipping_zone'], ENT_QUOTES, 'UTF-8'); |
20 |
$this->data['deliveryemail'] = $order_info['email']; |
21 |
$this->data['deliveryphone'] = html_entity_decode($order_info['telephone'], ENT_QUOTES, 'UTF-8'); |
22 |
$this->data['deliverypost'] = html_entity_decode($order_info['shipping_postcode'], ENT_QUOTES, 'UTF-8'); |
Cuối cùng, chúng tôi gán file custom.tpl tùy chỉnh của chúng tôi và xuất ra view.
1 |
if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/payment/custom.tpl')){ |
2 |
$this->template = $this->config->get('config_template') . '/template/payment/custom.tpl'; |
3 |
} else { |
4 |
$this->template = 'default/template/payment/custom.tpl'; |
5 |
}
|
6 |
|
7 |
$this->render(); |
Hãy xem lại code của phương thức callback. Phương thức này sẽ được gọi khi người dùng quay lại cửa hàng từ trang cổng thanh toán.
Trước tiên, chúng tôi kiểm tra xem biến orderid có khả dụng hay không trước khi tiếp tục. Nếu không, đơn giản chúng tôi dừng việc xử lý tiếp theo.
1 |
if (isset($this->request->post['orderid'])) { |
2 |
$order_id = trim(substr(($this->request->post['orderid']), 6)); |
3 |
} else { |
4 |
die('Illegal Access'); |
5 |
}
|
Tiếp theo, chúng tôi tải thông tin đơn đặt hàng từ cơ sở dữ liệu. Và cuối cùng, chúng tôi sẽ kiểm tra xem liệu chúng tôi nhận được chỉ báo thành công từ phản hồi cổng thanh toán hay không. Nếu đúng như vậy, chúng tôi sẽ tiếp tục và cập nhật thông tin trạng thái đơn hàng cho phù hợp.
1 |
$this->load->model('checkout/order'); |
2 |
$order_info = $this->model_checkout_order->getOrder($order_id); |
3 |
|
4 |
if ($order_info) { |
5 |
$data = array_merge($this->request->post,$this->request->get); |
6 |
|
7 |
//payment was made succ
|
8 |
if ($data['status'] == 'Y' || $data['status'] == 'y') { |
9 |
// update the order status accordingly
|
10 |
}
|
11 |
}
|
Vậy là controller đã được thiết lập. Đơn giản, phải không?
Model truyền thống
Như bạn biết, OpenCart có tập hợp các quy ước và tiêu chuẩn riêng để xử lý các hoạt động nội bộ của cửa hàng. Chẳng hạn như trường hợp với thiết lập model để phát hiện phương thức thanh toán. Bạn chỉ cần thiết lập nó theo các quy ước, và nó sẽ được chọn tự động.
Hãy tiếp tục và tạo file model tại catalog/model/payment/custom.php. Dán các nội dung sau vào file custom.php vừa được tạo.
1 |
<?php
|
2 |
class ModelPaymentCustom extends Model { |
3 |
public function getMethod($address, $total) { |
4 |
$this->load->language('payment/custom'); |
5 |
|
6 |
$method_data = array( |
7 |
'code' => 'custom', |
8 |
'title' => $this->language->get('text_title'), |
9 |
'sort_order' => $this->config->get('custom_sort_order') |
10 |
);
|
11 |
|
12 |
return $method_data; |
13 |
}
|
14 |
}
|
Class này sẽ được OpenCart sử dụng khi liệt kê các phương thức thanh toán đang hoạt động trong quá trình thanh toán. Trong quá trình này, OpenCart thu thập danh sách các phương thức thanh toán hoạt động từ back-end và đối với mỗi phương thức, nó sẽ kiểm tra xem class model thích hợp có sẵn hay không. Phương thức thanh toán sẽ chỉ được liệt kê nếu một lớp mô hình liên kết có sẵn.
Điều quan trọng trong thiết lập này là giá trị của biến mã. Trong trường hợp của chúng tôi, chúng tôi đã xác định nó thành tùy chỉnh, có nghĩa là khi bạn chọn phương thức thanh toán và nhấn Tiếp tục, nó sẽ gọi URL thanh toán / tùy chỉnh nội bộ, cuối cùng thiết lập biểu mẫu cho cổng thanh toán của chúng tôi.
Tóm lại, chúng ta có thể nói rằng đó là một tập tin bắt buộc cho việc phát hiện và làm việc đúng đắn của phương thức thanh toán trong front-end.
Tệp ngôn ngữ và mẫu
Bây giờ, chúng ta chỉ cần tạo ngôn ngữ và xem các tập tin. Hãy tiếp tục và tạo tệp ngôn ngữ tại catalog / language / english / payment / custom.php. Dán các nội dung sau vào tệp ngôn ngữ mới được tạo custom.php.
1 |
<?php |
2 |
$_['text_title'] = 'Custom Payment Method'; |
3 |
$_['button_confirm'] = 'Confirm Order'; |
4 |
?> |
Khá dễ hiểu: chúng tôi vừa thiết lập các nhãn sẽ được sử dụng ở mặt trước trong quá trình thanh toán.
Hãy tiếp tục và tạo tệp mẫu tại danh mục / xem / chủ đề / mặc định / mẫu / thanh toán / custom.tpl. Dán các nội dung sau vào tệp mẫu custom.tpl mới được tạo.
1 |
<form action="<?php echo $action; ?>" method="post"> |
2 |
<input type="hidden" name="text_config_one" value="<?php echo $text_config_one; ?>" /> |
3 |
<input type="hidden" name="text_config_two" value="<?php echo $text_config_two; ?>" /> |
4 |
<input type="hidden" name="orderid" value="<?php echo $orderid; ?>" /> |
5 |
<input type="hidden" name="callbackurl" value="<?php echo $callbackurl; ?>" /> |
6 |
<input type="hidden" name="orderdate" value="<?php echo $orderdate; ?>" /> |
7 |
<input type="hidden" name="currency" value="<?php echo $currency; ?>" /> |
8 |
<input type="hidden" name="orderamount" value="<?php echo $orderamount; ?>" /> |
9 |
<input type="hidden" name="billemail" value="<?php echo $billemail; ?>" /> |
10 |
<input type="hidden" name="billphone" value="<?php echo $billphone; ?>" /> |
11 |
<input type="hidden" name="billaddress" value="<?php echo $billaddress; ?>" /> |
12 |
<input type="hidden" name="billcountry" value="<?php echo $billcountry; ?>" /> |
13 |
<input type="hidden" name="billprovince" value="<?php echo $billprovince; ?>" /> |
14 |
<input type="hidden" name="billcity" value="<?php echo $billcity; ?>" /> |
15 |
<input type="hidden" name="billpost" value="<?php echo $billpost; ?>" /> |
16 |
<input type="hidden" name="deliveryname" value="<?php echo $deliveryname; ?>" /> |
17 |
<input type="hidden" name="deliveryaddress" value="<?php echo $deliveryaddress; ?>" /> |
18 |
<input type="hidden" name="deliverycity" value="<?php echo $deliverycity; ?>" /> |
19 |
<input type="hidden" name="deliverycountry" value="<?php echo $deliverycountry; ?>" /> |
20 |
<input type="hidden" name="deliveryprovince" value="<?php echo $deliveryprovince; ?>" /> |
21 |
<input type="hidden" name="deliveryemail" value="<?php echo $deliveryemail; ?>" /> |
22 |
<input type="hidden" name="deliveryphone" value="<?php echo $deliveryphone; ?>" /> |
23 |
<input type="hidden" name="deliverypost" value="<?php echo $deliverypost; ?>" /> |
24 |
|
25 |
<div class="buttons"> |
26 |
<div class="right"> |
27 |
<input type="submit" value="<?php echo $button_confirm; ?>" class="button" /> |
28 |
</div>
|
29 |
</div>
|
30 |
</form>
|
Như bạn có thể đoán, đây là biểu mẫu sẽ được gửi khi người dùng nhấp vào nút Xác nhận đơn đặt hàng. Chúng tôi vừa thiết lập các biến ẩn và giá trị của chúng đã được xác định trước đó trong phương pháp chỉ mục của bộ điều khiển.
Hãy xem mọi thứ trông như thế nào trên giao diện người dùng:



Hãy nhanh chóng xem qua quy trình tổng quát:
- Trước tiên, bạn phải thiết lập file model cho phương thức thanh toán của mình để có thể liệt kê trong bước 5: Phương thức thanh toán.
- Tiếp theo, khi người dùng chọn Custom Payment Method trong tab thứ năm và nhấp vào nút Continue, OpenCart trong gọi URL payment/custom, phương thức này sẽ gọi phương thức index cuối cùng và hiển thị file custom.tpl trong tab thứ sáu.
- Sau cùng, khi người dùng nhấp vào nút Confirm Order, biểu mẫu sẽ được gửi đi và người dùng được đưa đến trang cổng thanh toán mà quá trình thanh toán xử lý. Khi quá trình thanh toán hoàn tất, người dùng sẽ được chuyển hướng trở lại website của chúng tôi, nhờ vào biến hidden gọi callbackurl. Tất nhiên, trạng thái đơn đặt hàng sẽ được cập nhật như một phần của phương thức callback nếu mọi thứ suôn sẻ. Một khi quá trình thanh toán hoàn tất, người dùng sẽ chuyển hướng trở về trang của chúng tôi, cảm ơn biến hidden callback. Dĩ nhiên, trạng thái đơn hàng sẽ được cập nhật theo chức năng của phương thức callback như mong đợi.
Tổng kết
Trong loạt bài này, tôi đã giải thích cách thiết lập hầu hết mọi phương thức thanh toán bằng cách tạo mô-đun phương thức thanh toán của riêng bạn. Tôi hy vọng bạn thích loạt bài này và đã học được điều hữu ích.
Xây dựng những công cụ tuỳ biến cho bất kỳy framework nào luôn thú vị, phải không? Hãy nhớ rằng bạn luôn có thể nhận xét và đặt câu hỏi bằng cách sử dụng form nhận xét bên dưới.