1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-17 06:52:27 +01:00

WIP: create payment schedule w/ payzen

This commit is contained in:
Sylvain 2021-04-29 17:10:02 +02:00
parent aaf36dcc0a
commit 5f47624d4e
6 changed files with 58 additions and 9 deletions

View File

@ -61,6 +61,11 @@ class API::PayzenController < API::PaymentsController
render json: e, status: :unprocessable_entity
end
def confirm_payment_schedule
# TODO
raise NotImplementedError
end
private
def on_reservation_success(order_id, details)

View File

@ -2,7 +2,13 @@ import apiClient from './clients/api-client';
import { AxiosResponse } from 'axios';
import { CartItems } from '../models/payment';
import { User } from '../models/user';
import { CheckHashResponse, ConfirmPaymentResponse, CreatePaymentResponse, SdkTestResponse } from '../models/payzen';
import {
CheckHashResponse,
ConfirmPaymentResponse,
CreatePaymentResponse,
CreateTokenResponse,
SdkTestResponse
} from '../models/payzen';
export default class PayzenAPI {
@ -16,7 +22,7 @@ export default class PayzenAPI {
return res?.data;
}
static async chargeCreateToken(cartItems: CartItems, customer: User): Promise<any> {
static async chargeCreateToken(cartItems: CartItems, customer: User): Promise<CreateTokenResponse> {
const res: AxiosResponse = await apiClient.post('/api/payzen/create_token', { cart_items: cartItems, customer_id: customer.id });
return res?.data;
}
@ -30,4 +36,9 @@ export default class PayzenAPI {
const res: AxiosResponse<ConfirmPaymentResponse> = await apiClient.post('/api/payzen/confirm_payment', { cart_items: cartItems, order_id: orderId });
return res?.data;
}
static async confirmSchedule(orderId: string, cartItems: CartItems): Promise<any> {
const res: AxiosResponse<any> = await apiClient.post('/api/payzen/confirm_payment_schedule', { cart_items: cartItems, order_id: orderId });
return res?.data;
}
}

View File

@ -1,12 +1,16 @@
import React, { FormEvent, FunctionComponent, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import KRGlue from "@lyracom/embedded-form-glue";
import { GatewayFormProps } from '../abstract-payment-modal';
import SettingAPI from '../../../api/setting';
import { SettingName } from '../../../models/setting';
import PayzenAPI from '../../../api/payzen';
import { Loader } from '../../base/loader';
import { KryptonClient, KryptonError, ProcessPaymentAnswer } from '../../../models/payzen';
import {
CreateTokenResponse,
KryptonClient,
KryptonError,
ProcessPaymentAnswer
} from '../../../models/payzen';
/**
* A form component to collect the credit card details and to create the payment method on Stripe.
@ -14,14 +18,13 @@ import { KryptonClient, KryptonError, ProcessPaymentAnswer } from '../../../mode
*/
export const PayzenForm: React.FC<GatewayFormProps> = ({ onSubmit, onSuccess, onError, children, className, paymentSchedule = false, cartItems, customer, operator, formId }) => {
const { t } = useTranslation('shared');
const PayZenKR = useRef<KryptonClient>(null);
const [loadingClass, setLoadingClass] = useState<'hidden' | 'loader' | 'loader-overlay'>('loader');
useEffect(() => {
const api = new SettingAPI();
api.query([SettingName.PayZenEndpoint, SettingName.PayZenPublicKey]).then(settings => {
PayzenAPI.chargeCreatePayment(cartItems, customer).then(formToken => {
createToken().then(formToken => {
// Load the remote library
KRGlue.loadLibrary(settings.get(SettingName.PayZenEndpoint), settings.get(SettingName.PayZenPublicKey))
.then(({ KR }) =>
@ -38,6 +41,18 @@ export const PayzenForm: React.FC<GatewayFormProps> = ({ onSubmit, onSuccess, on
});
}, [cartItems, paymentSchedule, customer]);
/**
* Ask the API to create the form token.
* Depending on the current transaction (schedule or not), a PayZen Token or Payment may be created.
*/
const createToken = async (): Promise<CreateTokenResponse> => {
if (paymentSchedule) {
return await PayzenAPI.chargeCreateToken(cartItems, customer);
} else {
return await PayzenAPI.chargeCreatePayment(cartItems, customer);
}
}
/**
* Callback triggered on PayZen successful payments
* @see https://docs.lyra.com/fr/rest/V4.0/javascript/features/reference.html#kronsubmit
@ -48,7 +63,7 @@ export const PayzenForm: React.FC<GatewayFormProps> = ({ onSubmit, onSuccess, on
const transaction = event.clientAnswer.transactions[0];
if (event.clientAnswer.orderStatus === 'PAID') {
PayzenAPI.confirm(event.clientAnswer.orderDetails.orderId, cartItems).then((confirmation) => {
confirm(event).then((confirmation) => {
PayZenKR.current.removeForms().then(() => {
onSuccess(confirmation);
});
@ -58,10 +73,21 @@ export const PayzenForm: React.FC<GatewayFormProps> = ({ onSubmit, onSuccess, on
onError(error || event.clientAnswer.orderStatus);
}
}
})
});
return true;
};
/**
* Ask the API to confirm the processed transaction, depending on the current transaction (schedule or not).
*/
const confirm = async (paymentAnswer: ProcessPaymentAnswer): Promise<any> => {
if (paymentSchedule) {
return await PayzenAPI.confirm(paymentAnswer.clientAnswer.orderDetails.orderId, cartItems);
} else {
return await PayzenAPI.confirmSchedule(paymentAnswer.clientAnswer.orderDetails.orderId, cartItems);
}
}
/**
* Callback triggered when the PayZen form was entirely loaded and displayed
* @see https://docs.lyra.com/fr/rest/V4.0/javascript/features/reference.html#%C3%89v%C3%A9nements

View File

@ -2,11 +2,13 @@ export interface SdkTestResponse {
success: boolean
}
export interface CreatePaymentResponse {
export interface CreateTokenResponse {
formToken: string
orderId: string
}
export interface CreatePaymentResponse extends CreateTokenResponse {}
export interface ConfirmPaymentResponse {
todo?: any
}

View File

@ -0,0 +1,4 @@
# frozen_string_literal: true
json.formToken @result['answer']['formToken']
json.orderId @id

View File

@ -185,6 +185,7 @@ Rails.application.routes.draw do
post 'payzen/confirm_payment' => 'payzen#confirm_payment'
post 'payzen/check_hash' => 'payzen#check_hash'
post 'payzen/create_token' => 'payzen#create_token'
post 'payzen/confirm_payment_schedule' => 'payzen#confirm_payment_schedule'
# FabAnalytics
get 'analytics/data' => 'analytics#data'