php - 这个上下文的流程应该是怎样的?(根据选择的付款方式,将处理付款的代码放在哪里?)
问题描述
我有一个用户在会议中注册的多步骤表单,所有步骤都在同一registration.blade.php
页面中,在第 1 步和第 2 步中完成了一个 ajax 请求以验证表单字段。
步骤是:
- 第 1 步是收集有关用户的一些信息(姓名和罐号)
- 第 2 步是收集付款方式(信用卡或参考资料)
- 第三步是付款
- 第4步显示成功消息(此步骤仅在使用信用卡成功付款后出现,参考付款方式此步骤不出现,参考付款方式仅出现步骤1、2和3)
我的疑问是在第 2 步和第 3 步之间。
如果选择的支付方式引用是执行以下代码所必需的,则生成一些支付引用,然后在步骤 3 中将该引用呈现给用户。当用户支付时,系统会收到通知并应将其插入到支付表中price
,payment_method_id
,registration_id
和status
(付费)。
使用参考处理付款的代码:
public function ReferencesCharge(Request $request)
{
$payment_info = [
'name' => "user name",
'email' => 'user email',
'value' => 'registration total price',
'id' => 'registration id',
];
$newPayment = new Payment($payment_info);
$reference = $newPayment->gererateReferences();
//$reference returns an array with necessary codes to present to the user so he can pay
// after generate references is necessary:
// show in step 3 the generated references
// insert an entry in the payments table when the system receives a notification from 3rd party service informing that the user did the payment
}
如果选择的付款是信用卡,则需要执行下面的代码以向信用卡收费,然后将、price
和(已付款) 插入到付款表中。然后应该将用户重定向到第 4 步以显示成功消息:payment_method_id
registration_id
status
处理信用卡付款的代码:
public function creditCardCharge(Request $request)
{
Stripe::setApiKey(config('services.stripe.secret'));
$source = $request->stripeToken;
try{
Charge::create([
'currency' => 'eur',
'amount' => 2500,
'source' => $source,
]);
}
catch(\Exception $e){
return response()->json(['status' => $e->getMessage()], 422);
}
// after charging the card with success:
// insert an entry in the payments table
// redirect to success confirmation step to inform the user that payment was done with success
}
我的疑问是流程应该如何,应该将处理带有参考的付款的代码和处理信用卡付款的代码放在哪里。所以有可能实现这种情况:
现在,我只有第 1 步和第 2 步正常工作。要处理 step1 和 step2 我有RegistrationController
. 在第 1 步中,使用 ajax 发布请求验证用户介绍的信息,如果返回用户转到第 2 步的storeUserInfo()
方法。RegistrationController
200
在步骤 2 中,用户选择付款方式并单击“转到步骤 3”,也会向 ajax 请求以storePaymentMethods()
验证RegistrationController
用户是否选择了至少一种付款方式。我的疑问是在此方法返回代码 200 之后该过程应该如何。
根据付款方式,有必要运行上面的相应代码(生成付款参考的代码或向信用卡收费的代码)。
因此,我怀疑如何根据控制器和方法组织此代码,根据所选的付款方式将应该执行的代码放在哪里。你知道流程应该如何实现吗?
也许一种方法可以如下所示,storePaymentMethods()
但在此方法中执行所有操作似乎都不是很正确:
public function storePaymentMethods(Request $request){
$request->validate([
'payment_method' => 'required',
]);
if($request->payment_method == "references"){
// generate codes and present to the user that codes
}
else if($request->payment_method == "credit_card"){
// show credit card inputs to the user
// and process the credit card payment with stripe
}
return response()->json([
'success' => true,
'message' => 'success',
'payment_method' => $request->payment_method,
], 200);
}
使用我现在拥有的多步表格注册流程的完整摘要:
所以对于step1,有以下形式:
<div>
<form method="post" id="step1form" action="">
{{csrf_field()}}
<!-- fields of the step 1-->
<input type="submit" href="#step2" id="goToStep2" class="btn next-step" value="Go to step 2"/>
</form>
</div>
step1 图片更好地解释:
当用户单击“转到步骤 2”按钮时,会发出 ajax 请求以验证数据,如果没有错误,则返回代码 200,用户转到步骤 2:
$('#goToStep2').on('click', function (event) {
event.preventDefault();
var custom_form = $("#" + page_form_id_step1);
$.ajax({
method: "POST",
url: '{{ route('conferences.storeRegistrationInfo', compact('id','slug') ) }}',
data: custom_form.serialize(),
datatype: 'json',
success: function (data, textStatus, jqXHR) {
var $active = $('.nav-pills li a.active');
nextTab($active);
},
error: function (data) {
// show errors
}
});
});
然后在 ConferencesController 中有 storeRegistrationInfo() 来处理上述 ajax 请求:
public function storeRegistrationInfo(Request $request, $id, $slug = null, Validator $validator){
$rules = [];
$messages = [];
$rules["name_invoice"] = 'required|max:255|string';
$rules["TIN_invoice"] = ['required', 'string', new ValidTIN()];
$validator = Validator::make($request->all(), $rules, $messages);
$errors = $validator->errors();
$errors = json_decode($errors);
if($validator->fails()) {
return response()->json([
'success' => false,
'errors' => $errors
], 422);
}
return response()->json([
'success' => true,
'message' => 'success'
], 200);
}
因此,如果返回代码 200,则用户在 step2form 中:
<div>
<form method="post" id="step2form" action="">
{{csrf_field()}}
<!-- fields of the step 2-->
<input type="submit" href="#step3" id="goToStep3" class="btn next-step" value="Go to step 3"/>
</form>
</div>
step2 图片更好地解释:
当用户单击“Go to step 3”按钮时,会发出 ajax 请求以验证数据,如果没有错误,则返回代码 200,用户转到第 3 步,ajax 请求:
$("#credit_card_section").hide();
$("#references_section").hide();
var page_form_id_step2 = "step2form";
$('#goToStep3').on('click', function (event) {
event.preventDefault();
var custom_form = $("#" + page_form_id_step2);
$.ajax({
method: "POST",
url: '{{ route('conferences.storePaymentMethods', compact('id','slug') ) }}',
data: custom_form.serialize(),
datatype: 'json',
success: function (data, textStatus, jqXHR) {
var result = data;
if(result['payment_method'] == 'credit_card'){
$("#credit_card_section").show();
$("#references_section").hide();
}else{
$("#references_section").show();
$("#credit_card_section").hide();
}
var $active = $('.nav-pills li a.active');
nextTab($active);
},
error: function (data) {
// show errors
}
});
});
ConferenceController 有 storePayment() 来处理上面的 ajax 请求,它验证用户是否选择了支付方式,如果是,则返回代码200
:
public function storePaymentMethods(Request $request){
$request->validate([
'payment_method' => 'required',
]);
return response()->json([
'success' => true,
'message' => 'success',
'payment_method' => $request->payment_method,
], 200);
}
然后是step3 div。在 step3 div 中,div 将根据上一步中选择的付款方式(信用卡或参考#credit_card_section
)显示为可见或可见:#references_section
<div>
<form method="post" id="step3form" action="">
{{csrf_field()}}
<div id="credit_card_section">
<!-- present necessary fields to
payments with credit card-->
</div>
<div id="references_section">
<!-- present generated reference to the user so he can pay-->
</div>
</form>
</div>
step3
图像更好地解释,根据付款方式,在步骤 3 中显示的必要信息是不同的。如果付款方式是信用卡,则step4
在使用信用卡成功收费后,还会出现一个显示成功消息的 div:
然后是第 4 步 div,在使用信用卡完成付款后应该显示成功消息:
<div id="step4">
<p>
<i class="fa fa-plus" aria-hidden="true"></i>
Payment and registration completed with success.
</p>
</div>
// 恢复我现在拥有的 RegistrationController 的方法,RegistrationController 是我拥有的处理多步表单的控制器
class RegistrationController extends Controller
{
public :function storeQuantities(Request $request, $id, $slug = null){
// method that stores in session the ticket types
// selected by the user in the conference details page
Session::put('selectedRtypes', $selectedRtypes);
Session::put('allParticipants' , $allParticipants);
Session::put('customQuestions' , $selectedRtypes[$rtype->name]['questions']);
// and then redirects the user to the registartion page registration.blade.php
// using the route 'conferences.registration
// this route is associated with the displayRegistrationPage() method
return redirect(route('conferences.registration',['id' => $id, 'slug' => $slug]));
}
// method of the route 'conferences.registration' that displays
// the registration.blade.php that is the page with the multi step form
public function displayRegistrationPage(Request $request, $id, $slug=null){
// get the session values
$selectedRtypes = Session::get('selectedRtypes');
$allParticipants = Session::get('allParticipants');
$customQuestions = Session::get('customQuestions');
// redirect the user to the registration.blade.php
if(isset($selectedRtypes)) {
return view('conferences.registration',
['selectedRtypes' => $selectedRtypes, 'customQuestions' => $customQuestions, 'id' => $id, 'slug' => $slug]);
}
else{
// return user to the conference details page
return redirect(route('conferences.show',['id' => $id, 'slug' => $slug]));
}
}
/* the following methods are to handle the registration
multi step form of the registration.blade.php view */
// method to handle the step1 of the multi step form
public function storeRegistrationInfo(Request $request, $id, $slug = null, Validator $validator){
// get and validate the fields of the step1
// and returns code 200 if al is ok
return response()->json([
'success' => true,
'message' => 'success'
], 200);
}
// method to handle the step2 of the multi step form
public function storePaymentMethods(Request $request){
// validate if the payment_method field was filled
// if was filled return code 200
// and returns the payment_method
//so in the step 3 div is possible to show a section for
// when the payment_method is credit card (#credit_card_section)
or transfers ("transfers_section")
return response()->json([
'success' => true,
'message' => 'success',
'payment_method' => $request->payment_method,
], 200);
}
}
路线step1
:
Route::post('/conference/{id}/{slug?}/registration/storeRegistrationInfo', [
'uses' => 'RegistrationController@storeRegistrationInfo',
'as' =>'conferences.storeRegistrationInfo'
]);
路线step2
:
Route::post('/conference/{id}/{slug?}/registration/storePaymentMethods', [
'uses' => 'RegistrationController@storePaymentMethods',
'as' =>'conferences.storePaymentMethods'
]);
解决方案
正如您所怀疑的那样,为了更好地构建代码和分离逻辑(DRY 概念),您应该做几件事:
使用 3 个函数创建
PaymentsController
(首先,您肯定会在此处添加更多函数)- 用于处理您的参考资料
- 用于处理信用卡
- 用于存储支付方式(在会话中存储支付方式,直到用户完成第 3 步)
对于如何命名这些函数,您完全自由,但我建议使用
processViaReferences
,processViaCreditCard
和storePaymentMethod
.如果您将它们分开,它将更容易阅读和验证。
在代码中为它们创建相应的发布路线并适当地引用。
创建仅包含您的表单的零件视图。
然后包括这些部分视图,
@include
以便在视图级别将其分开。对于您在 javascript/jQuery 中的引用,请记住保留它们的正确 ID。如果您还没有这样做,您也可以将 javascript 提取到其他视图部分视图或单独的 js 文件。您的视图/表单代码应该转到这些部分视图...
推荐阅读
- php - PHP PDO bindValue() 绑定 null 而不是 value
- python - 将 for 循环转换为列表推导以形成字典
- python - 不能在不改变颜色的情况下覆盖蒙版?
- java - 我有一个算法,但不知道它如何工作或为什么工作
- python - 在 python 中共享记录器
- conda - 对于声明为本地的规则,未在 snakemake 中激活 Conda 环境
- node.js - 我无法在 Xubuntu 20.04 上安装 heapdump
- java - 如何使用 getScaleController() 和 PinchGesture?
- reactjs - React Hook SetState 导致无限循环
- javascript - 有限状态算法