@unchainedshop/plugins 4.8.17 → 4.8.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ import type { Order } from '@unchainedshop/core-orders';
2
+ export interface Cardholder {
3
+ cardholderName?: string;
4
+ email?: string;
5
+ homePhone?: {
6
+ cc: string;
7
+ subscriber: string;
8
+ };
9
+ }
10
+ export default function build3DSCardholder(order?: Order): Cardholder | undefined;
11
+ export declare const withCardCardholder: (arbitraryFields: any, cardholder?: Cardholder) => any;
12
+ export declare const withSecureFieldsCardholder: (arbitraryFields: any, cardholder?: Cardholder) => any;
@@ -0,0 +1,44 @@
1
+ import { phoneNumberToParts } from '@unchainedshop/utils';
2
+ export default function build3DSCardholder(order) {
3
+ if (!order)
4
+ return undefined;
5
+ const { billingAddress, contact } = order;
6
+ const cardholderName = [billingAddress?.firstName, billingAddress?.lastName].filter(Boolean).join(' ');
7
+ const homePhone = phoneNumberToParts(contact?.telNumber, billingAddress?.countryCode);
8
+ const cardholder = {};
9
+ if (cardholderName)
10
+ cardholder.cardholderName = cardholderName;
11
+ if (contact?.emailAddress)
12
+ cardholder.email = contact.emailAddress;
13
+ if (homePhone)
14
+ cardholder.homePhone = homePhone;
15
+ if (Object.keys(cardholder).length === 0)
16
+ return undefined;
17
+ return cardholder;
18
+ }
19
+ const mergeCardholder = (container, cardholder) => {
20
+ const threeDS = container?.['3D'] || {};
21
+ return {
22
+ ...container,
23
+ '3D': {
24
+ ...threeDS,
25
+ cardholder: {
26
+ ...cardholder,
27
+ ...(threeDS.cardholder || {}),
28
+ },
29
+ },
30
+ };
31
+ };
32
+ export const withCardCardholder = (arbitraryFields, cardholder) => {
33
+ if (!cardholder)
34
+ return arbitraryFields;
35
+ return {
36
+ ...arbitraryFields,
37
+ card: mergeCardholder(arbitraryFields?.card, cardholder),
38
+ };
39
+ };
40
+ export const withSecureFieldsCardholder = (arbitraryFields, cardholder) => {
41
+ if (!cardholder)
42
+ return arbitraryFields;
43
+ return mergeCardholder(arbitraryFields, cardholder);
44
+ };
@@ -2,6 +2,7 @@ import { createLogger } from '@unchainedshop/logger';
2
2
  import createDatatransAPI from "./api/index.js";
3
3
  import parseRegistrationData from "./parseRegistrationData.js";
4
4
  import roundedAmountFromOrder from "./roundedAmountFromOrder.js";
5
+ import build3DSCardholder, { withCardCardholder, withSecureFieldsCardholder, } from "./build3DSCardholder.js";
5
6
  import { PaymentAdapter, PaymentDirector, PaymentError, PaymentPricingRowCategory, PaymentPricingSheet, OrderPricingSheet, } from '@unchainedshop/core';
6
7
  const logger = createLogger('unchained:datatrans');
7
8
  const { DATATRANS_SECRET, DATATRANS_SIGN_KEY, DATATRANS_API_ENDPOINT = 'https://api.sandbox.datatrans.com', DATATRANS_MERCHANT_ID, } = process.env;
@@ -224,22 +225,18 @@ const Datatrans = {
224
225
  const price = order
225
226
  ? roundedAmountFromOrder(order)
226
227
  : {};
228
+ const cardholder = build3DSCardholder(order);
227
229
  if (useSecureFields) {
228
230
  const result = await api().secureFields({
229
- ...arbitraryFields,
231
+ ...withSecureFieldsCardholder(arbitraryFields, cardholder),
230
232
  currency: price.currencyCode || 'CHF',
231
- refno,
232
- refno2,
233
- customer: {
234
- id: userId,
235
- },
236
233
  amount: price.amount,
237
234
  });
238
235
  throwIfResponseError(result);
239
236
  return JSON.stringify(result);
240
237
  }
241
238
  const result = await api().init({
242
- ...arbitraryFields,
239
+ ...withCardCardholder(arbitraryFields, cardholder),
243
240
  currency: price.currencyCode || 'CHF',
244
241
  refno,
245
242
  refno2,
@@ -352,11 +349,17 @@ const Datatrans = {
352
349
  if (status === 'authenticated') {
353
350
  if (authorizeAuthenticated) {
354
351
  checkIfTransactionAmountValid(transactionId, transaction);
352
+ const { orderPayment, order } = context;
353
+ const userId = order?.userId || context?.userId;
354
+ const refno = orderPayment
355
+ ? Buffer.from(orderPayment._id, 'hex').toString('base64')
356
+ : transaction.refno;
357
+ const refno2 = userId || transaction.refno2;
355
358
  await authorizeAuth({
356
359
  ...(authorizeAuthenticated || {}),
357
360
  transactionId,
358
- refno: transaction.refno,
359
- refno2: transaction.refno2,
361
+ refno,
362
+ refno2,
360
363
  });
361
364
  status = 'authorized';
362
365
  }
@@ -10,7 +10,7 @@ else {
10
10
  try {
11
11
  const { default: Stripe } = await import('stripe');
12
12
  stripe = new Stripe(STRIPE_SECRET, {
13
- apiVersion: '2026-05-27.dahlia',
13
+ apiVersion: '2026-06-24.dahlia',
14
14
  });
15
15
  }
16
16
  catch {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@unchainedshop/plugins",
3
3
  "description": "Official plugin collection for the Unchained Engine with payment, delivery, and pricing adapters",
4
- "version": "4.8.17",
4
+ "version": "4.8.18",
5
5
  "main": "lib/plugins-index.js",
6
6
  "types": "lib/plugins-index.d.ts",
7
7
  "exports": {