I have a multi-step form for a user to register in a conference, all steps are in the same registration.blade.php
page, in step 1 and step 2 is done an ajax request to validate the form fields.
这些步骤是:
- Step1 is to collect some info about the user (name and tin number)
- 第2步是收取付款方式(credit card or references)
- Step 3 is the payment
- 第4步显示成功消息(this step only appears after a successful payment with a credit card, with the references payment method this step don't appear, with references payment method only the step 1, 2 and 3 appears)
我的怀疑介于第二步和第三步之间.
If the selected payment method references is necessary to execute the code below, that generates some payment references and then present that references to the user in step 3. When the user pays the system receives a notification and should be inserted in the payments table the price
, payment_method_id
, registration_id
and status
(paid).
Code to process payments with references:个
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
}
如果 Select 的付款是信用卡,则需要执行下面的代码以向信用卡收费,然后将其插入付款表price
、payment_method_id
、registration_id
和status
(paid).然后,用户应该被重定向到步骤4,以显示一条成功消息:
Code to process credit card payments:
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
}
My doubt is how the flow should be, where the code to handle the payment with references and the code to handle the payment with a credit card should be placed. So is possible to achieve this scenario:
For now, I just have the step 1 and step 2 working properly. To handle step1 and step2 I have the RegistrationController
. In the step1 the info introduced by the user is validated using an ajax post request to the storeUserInfo()
method of the RegistrationController
if returns 200
the user goes to step2.
In the step2, the user selects the payment method and clicks in "go to step 3" is also done an ajax request to the storePaymentMethods()
of the RegistrationController
to validate if the user selected at least 1 payment method. My doubt is after this method return code 200 how the process should be.
根据付款方式的不同,需要运行上面的相应代码(code that generates payment references or code to charge credit card).
因此,我怀疑如何从控制器和方法的Angular 组织这些代码,根据所选的支付方法,将应该执行的代码放在何处.你知道流程应该如何实现这一点吗?
Maybe an approach can be something like below in storePaymentMethods()
but it doesn't seem very correct do everything in this method:
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);
}
A full summary of the flow of the registration with the multistep form that I have for now:
So for the step1, there is the form:
<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 image to explain better:
当用户点击"Go to Step 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
}
});
});
Then in the ConferencesController there is teh storeRegistrationInfo() to handle the above ajax request:
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图像更好地解释:
当用户点击"转到步骤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请求,它验证用户是否 Select 了支付方式,如果 Select 了,则返回代码200
:
public function storePaymentMethods(Request $request){
$request->validate([
'payment_method' => 'required',
]);
return response()->json([
'success' => true,
'message' => 'success',
'payment_method' => $request->payment_method,
], 200);
}
Then there is the step3 div. In the step3 div it will appear the div #credit_card_section
visible or #references_section
visible depending on the payment method selected in the previous step (credit card or references):
<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
image to explain better, depending on the payment method the info that is necessary to show in step 3 is different. If the payment method was credit card also appears a step4
div showing a success message after a successful charge with a credit card:
然后是step 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'
]);
Route for step2
:
Route::post('/conference/{id}/{slug?}/registration/storePaymentMethods', [
'uses' => 'RegistrationController@storePaymentMethods',
'as' =>'conferences.storePaymentMethods'
]);