@akinon/pz-haso
v2.0.43
Published
HASO (Hemen Al Sonra Öde / Buy Now Pay Later) ödeme entegrasyonu için data aggregation paketi.
Readme
HASO Payment Gateway Extension
HASO (Hemen Al Sonra Öde / Buy Now Pay Later) ödeme entegrasyonu için data aggregation paketi.
Installation
You can use the following command to install the extension with the latest plugins:
npx @akinon/projectzero@latest --pluginsUsage
Once the extension is installed, you can easily integrate the HASO payment gateway into your application. Here's an example of how to use it.
Navigate to the
src/app/[commerce]/[locale]/[currency]/payment-gateway/haso/directory.Create a file named
page.tsxand include the following code:
import { HasoPaymentGateway } from '@akinon/pz-haso';
const HasoGateway = async ({
searchParams: { sessionId },
params: { currency, locale }
}: {
searchParams: Record<string, string>;
params: { currency: string; locale: string };
}) => {
return (
<HasoPaymentGateway
sessionId={sessionId}
currency={currency}
locale={locale}
extensionUrl={process.env.HASO_EXTENSION_URL}
hashKey={process.env.HASO_HASH_KEY}
/>
);
};
export default HasoGateway;Customizing the HASO Component
You can customize the appearance of the HASO payment gateway using the renderer prop. This allows you to provide custom rendering functions for different parts of the component.
Custom Form Component
import { HasoPaymentGateway } from '@akinon/pz-haso';
const HasoGateway = async ({
searchParams: { sessionId },
params: { currency, locale }
}: {
searchParams: Record<string, string>;
params: { currency: string; locale: string };
}) => {
return (
<HasoPaymentGateway
sessionId={sessionId}
currency={currency}
locale={locale}
extensionUrl={process.env.HASO_EXTENSION_URL}
hashKey={process.env.HASO_HASH_KEY}
renderer={{
formComponent: {
renderForm: ({
extensionUrl,
sessionId,
context,
csrfToken,
autoSubmit
}) => (
<div className="custom-haso-form-wrapper">
<h3 className="text-lg font-semibold mb-4">HASO Ödeme</h3>
<p className="mb-4">
HASO ödeme sayfasına yönlendiriliyorsunuz...
</p>
<form
action={`${extensionUrl}/form-page/?sessionId=${sessionId}`}
method="post"
encType="multipart/form-data"
id="haso-custom-form"
className="hidden"
>
<input type="hidden" name="csrf_token" value={csrfToken} />
<input
type="hidden"
name="data"
value={JSON.stringify(context)}
/>
{autoSubmit && (
<script
dangerouslySetInnerHTML={{
__html:
"document.getElementById('haso-custom-form').submit()"
}}
/>
)}
</form>
<div className="loader w-12 h-12 border-4 border-t-4 border-gray-200 border-t-blue-500 rounded-full animate-spin"></div>
</div>
)
},
paymentGateway: {
renderContainer: ({ children }) => (
<div className="p-8 max-w-lg mx-auto bg-white rounded-lg shadow-md">
{children}
</div>
)
}
}}
/>
);
};
export default HasoGateway;Custom Renderer API
The renderer prop accepts an object with the following structure:
interface HasoRendererProps {
formComponent?: {
renderForm?: (props: {
extensionUrl: string;
sessionId: string;
context: any;
csrfToken: string;
autoSubmit: boolean;
}) => React.ReactNode;
renderLoading?: () => React.ReactNode;
renderError?: (error: string) => React.ReactNode;
};
paymentGateway?: {
renderContainer?: (props: { children: React.ReactNode }) => React.ReactNode;
};
}Configuration
Add these variables to your .env file:
HASO_EXTENSION_URL=<your_extension_url>
HASO_HASH_KEY=<your_hash_key>Data Aggregation Flow
This package implements the data aggregation pattern for HASO payments:
1. start-session → redirectUrl: /payment-gateway/haso/?sessionId=XXX
2. HasoPaymentGateway → Collects data (preOrder, addresses, basket)
3. FormComponent → POST → Extension /form-page/?sessionId=XXX (with SHA-512 hash)
4. Extension → Creates Provider URL → Payment screen
5. Payment completed → return-url → Merchant StoreData Collected
The package collects the following data from the checkout:
- Order Items: Product name, SKU, quantity, unit price, total amount
- Billing Address: City, country, name, address line, phone, email, postal code
- Shipping Address: City, country, name, address line, phone, email, postal code
- Customer Info: Name, phone, email, identity number
- Amounts: Total amount, shipping amount, currency
Security
All data is sent with a SHA-512 hash for validation:
- Hash is generated using:
salt | sessionId | hashKey - Extension validates the hash before processing
API Routes
Check Availability API
To enable HASO payment availability checks, you need to create an API route. Create a file at src/app/api/haso-check-availability/route.ts with the following content:
import { POST } from '@akinon/pz-haso/src/pages/api/check-availability';
export { POST };This API endpoint handles checking the availability of HASO payment for a given:
- Phone number
- Order amount
- Email (optional)
- Identity number (optional)
The endpoint automatically validates the request and response using hash-based security measures.
Using checkHasoAvailability Mutation
The extension provides a Redux mutation hook that you can use to check HASO payment availability. Here's an example of how to implement it:
import { useCheckHasoAvailabilityMutation } from '@akinon/pz-haso';
const YourComponent = () => {
const [checkHasoAvailability] = useCheckHasoAvailabilityMutation();
const [isHasoAvailable, setIsHasoAvailable] = useState(false);
useEffect(() => {
const checkAvailability = async () => {
try {
const response = await checkHasoAvailability({
amount: '1000.00',
phone: '+905551234567',
email: '[email protected]',
identity_number: '12345678901' // TC Kimlik No (optional)
}).unwrap();
setIsHasoAvailable(response.is_available);
} catch (error) {
console.error('Error checking HASO availability:', error);
setIsHasoAvailable(false);
}
};
checkAvailability();
}, [checkHasoAvailability]);
return (
// Your component JSX
);
};The mutation returns an object with the following properties:
is_available: boolean indicating if HASO payment is availablelimit: number indicating the available credit limit (optional)salt: string used for hash verificationhash: string for response validation
