strapi-plugin-payone-provider 1.6.5 → 1.6.7

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.
@@ -8,13 +8,35 @@ const POST_GATEWAY_URL = "https://api.pay1.de/post-gateway/";
8
8
 
9
9
  const parseResponse = (responseData) => {
10
10
  if (typeof responseData === 'string') {
11
+ if (responseData.trim().startsWith('{')) {
12
+ try {
13
+ return JSON.parse(responseData);
14
+ } catch (e) {
15
+ // Fall through to URL-encoded parsing
16
+ }
17
+ }
18
+
11
19
  const params = new URLSearchParams(responseData);
12
20
  const parsed = {};
13
21
  for (const [key, value] of params.entries()) {
14
22
  parsed[key] = value;
23
+ const normalizedKey = key.toLowerCase().replace(/\[/g, '_').replace(/\]/g, '');
24
+ if (normalizedKey !== key.toLowerCase()) {
25
+ parsed[normalizedKey] = value;
26
+ }
15
27
  }
16
28
  return parsed;
17
29
  }
30
+
31
+ if (typeof responseData === 'object' && responseData !== null) {
32
+ const result = { ...responseData };
33
+ if (result['add_paydata[applepay_payment_session]']) {
34
+ result.add_paydata = result.add_paydata || {};
35
+ result.add_paydata.applepay_payment_session = result['add_paydata[applepay_payment_session]'];
36
+ }
37
+ return result;
38
+ }
39
+
18
40
  return responseData;
19
41
  };
20
42
 
@@ -45,8 +67,6 @@ const initializeApplePaySession = async (strapi, params) => {
45
67
 
46
68
  const applePayConfig = settings?.applePayConfig || {};
47
69
  const currency = params.currency || applePayConfig.currencyCode || "EUR";
48
- const countryCode = params.countryCode || applePayConfig.countryCode || "DE";
49
-
50
70
  const merchantName = params.displayName || settings?.merchantName || "Store";
51
71
  const domain = params.domain || params.domainName || "localhost";
52
72
 
@@ -63,18 +83,14 @@ const initializeApplePaySession = async (strapi, params) => {
63
83
  const requestParams = buildClientRequestParams(settings, baseParams, strapi.log);
64
84
  const formData = toFormData(requestParams);
65
85
 
66
- let response;
67
- try {
68
- response = await axios.post(`${POST_GATEWAY_URL}Genericpayment`, formData, {
69
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
70
- timeout: 30000,
71
- validateStatus: function (status) {
72
- return status >= 200 && status < 600;
73
- }
74
- });
75
- } catch (axiosError) {
76
- throw axiosError;
77
- }
86
+ const response = await axios.post(`${POST_GATEWAY_URL}Genericpayment`, formData, {
87
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
88
+ timeout: 30000,
89
+ validateStatus: function (status) {
90
+ return status >= 200 && status < 600;
91
+ }
92
+ });
93
+
78
94
 
79
95
  if (response.status === 403) {
80
96
  const responseData = parseResponse(response.data);
@@ -88,12 +104,7 @@ const initializeApplePaySession = async (strapi, params) => {
88
104
 
89
105
  const detailedError = new Error("403 Forbidden: Authentication failed with Payone API. " +
90
106
  (errorCode ? `Error Code: ${errorCode}. ` : "") +
91
- (errorMessage ? `Error: ${errorMessage}. ` : "") +
92
- "Please check: 1) Your Payone credentials (aid, portalid, mid, key) in plugin settings, " +
93
- "2) Mode is set to 'live' (Apple Pay only works in live mode), " +
94
- "3) Your domain is registered with Payone Merchant Services, " +
95
- "4) Merchant ID (mid) matches your merchantIdentifier in PMI, " +
96
- "5) Apple Pay is enabled for your portal in PMI.");
107
+ (errorMessage ? `Error: ${errorMessage}. ` : ""));
97
108
  Object.assign(detailedError, { status: 403, response: response });
98
109
  throw detailedError;
99
110
  }
@@ -138,71 +149,7 @@ const initializeApplePaySession = async (strapi, params) => {
138
149
 
139
150
  return responseData;
140
151
  } catch (error) {
141
- const errorStatus = error.response?.status || error.status;
142
- const errorResponseData = error.response?.data;
143
-
144
- // Provide more specific error messages
145
- if (errorStatus === 403 || error.message?.includes('403')) {
146
- let responseData = {};
147
- let errorCode = null;
148
- let errorMessage = null;
149
-
150
- if (errorResponseData) {
151
- try {
152
- responseData = parseResponse(errorResponseData);
153
- errorCode = responseData.errorcode || responseData.ErrorCode;
154
- errorMessage = responseData.errormessage || responseData.ErrorMessage || responseData.customermessage || responseData.CustomerMessage;
155
- } catch (parseErr) {
156
- if (typeof errorResponseData === 'string') {
157
- errorMessage = errorResponseData;
158
- }
159
- }
160
- }
161
-
162
- if (errorCode || errorMessage) {
163
- strapi.log.error("[Apple Pay] 403 Forbidden from Payone:", {
164
- errorcode: errorCode,
165
- errormessage: errorMessage
166
- });
167
- }
168
-
169
- let detailedMessage = "403 Forbidden: Authentication failed with Payone API. ";
170
-
171
- if (errorCode) {
172
- detailedMessage += `Error Code: ${errorCode}. `;
173
- }
174
-
175
- if (errorMessage) {
176
- detailedMessage += `Error: ${errorMessage}. `;
177
- }
178
-
179
- detailedMessage += "Please check:\n" +
180
- "1. Your Payone credentials (aid, portalid, mid, key) in plugin settings\n" +
181
- "2. Mode is set to 'live' (Apple Pay only works in live mode according to Payone docs)\n" +
182
- "3. Your domain is registered with Payone Merchant Services\n" +
183
- "4. Merchant ID (mid) matches your merchantIdentifier in PMI\n" +
184
- "5. Apple Pay is enabled for your portal in PMI (CONFIGURATION → PAYMENT PORTALS → [Your Portal] → Payment type configuration tab)";
185
-
186
- throw new Error(detailedMessage);
187
- } else if (errorStatus === 401 || error.message?.includes('401')) {
188
- if (errorResponseData) {
189
- const responseData = parseResponse(errorResponseData);
190
- strapi.log.error("[Apple Pay] 401 Unauthorized from Payone:", {
191
- errorcode: responseData.errorcode || responseData.ErrorCode,
192
- errormessage: responseData.errormessage || responseData.ErrorMessage
193
- });
194
- }
195
- throw new Error("401 Unauthorized: Invalid credentials. Please verify your Payone key in plugin settings.");
196
- } else if (errorStatus && errorStatus >= 500) {
197
- const responseData = errorResponseData ? parseResponse(errorResponseData) : {};
198
- strapi.log.error("[Apple Pay] Payone server error:", {
199
- status: error.response?.status,
200
- errorcode: responseData.errorcode || responseData.ErrorCode,
201
- errormessage: responseData.errormessage || responseData.ErrorMessage
202
- });
203
- throw new Error(`Payone server error (${error.response?.status}): ${error.response?.statusText || 'Internal server error'}`);
204
- }
205
-
152
+ strapi.log.error("[Apple Pay] Error:", error instanceof Error ? error.message : error);
206
153
  throw error;
207
154
  }
208
155
  };
@@ -215,28 +162,89 @@ const validateApplePayMerchant = async (strapi, params) => {
215
162
  throw new Error("Payone settings are not properly configured. Please check your plugin settings (aid, portalid, mid, key).");
216
163
  }
217
164
 
218
- // Get currency and country from Apple Pay config
219
165
  const applePayConfig = settings?.applePayConfig || {};
220
- const currency = params.currency || applePayConfig.currencyCode || "EUR";
221
- const countryCode = params.countryCode || applePayConfig.countryCode || "DE";
222
166
 
223
- // Update params with config values
224
167
  if (!params.currency && applePayConfig.currencyCode) {
225
168
  params.currency = applePayConfig.currencyCode;
226
169
  }
170
+
227
171
  if (!params.countryCode && applePayConfig.countryCode) {
228
172
  params.countryCode = applePayConfig.countryCode;
229
173
  }
230
174
 
231
175
  const sessionResponse = await initializeApplePaySession(strapi, params);
232
176
 
233
- const applePaySessionBase64 = sessionResponse["add_paydata[applepay_payment_session]"] ||
234
- sessionResponse.add_paydata?.applepay_payment_session;
177
+ // Extract add_paydata[applepay_payment_session] from response
178
+ // Payone returns this in URL-encoded format: add_paydata[applepay_payment_session]=BASE64_STRING
179
+ const applePaySessionBase64 =
180
+ sessionResponse["add_paydata[applepay_payment_session]"] ||
181
+ sessionResponse["add_paydata_applepay_payment_session"] ||
182
+ sessionResponse.add_paydata?.applepay_payment_session ||
183
+ (sessionResponse.add_paydata && typeof sessionResponse.add_paydata === 'object'
184
+ ? sessionResponse.add_paydata["applepay_payment_session"]
185
+ : null);
186
+
187
+ strapi.log.info("[Apple Pay] Genericpayment response:", {
188
+ status: sessionResponse.status,
189
+ workorderid: sessionResponse.workorderid,
190
+ hasApplePaySession: !!applePaySessionBase64,
191
+ applePaySessionLength: applePaySessionBase64 ? applePaySessionBase64.length : 0,
192
+ responseKeys: Object.keys(sessionResponse),
193
+ hasAddPaydataKey: !!sessionResponse["add_paydata[applepay_payment_session]"],
194
+ hasAddPaydataObject: !!sessionResponse.add_paydata,
195
+ addPaydataKeys: sessionResponse.add_paydata ? Object.keys(sessionResponse.add_paydata) : null
196
+ });
197
+
198
+ if (!applePaySessionBase64) {
199
+ strapi.log.error("[Apple Pay] Missing applepay_payment_session in response:", {
200
+ status: sessionResponse.status,
201
+ responseKeys: Object.keys(sessionResponse),
202
+ responseSample: JSON.stringify(sessionResponse).substring(0, 1000),
203
+ addPaydataKeys: sessionResponse.add_paydata ? Object.keys(sessionResponse.add_paydata) : null
204
+ });
205
+ throw new Error("Missing applepay_payment_session in Payone response. Please check your Payone Apple Pay configuration in PMI.");
206
+ }
235
207
 
236
208
  if (sessionResponse.status === "OK" && applePaySessionBase64 && applePaySessionBase64.length > 0) {
237
209
  try {
238
- const merchantSessionJson = Buffer.from(applePaySessionBase64, 'base64').toString('utf-8');
239
- const merchantSession = JSON.parse(merchantSessionJson);
210
+ strapi.log.info("[Apple Pay] Extracting merchant session from Base64:", {
211
+ base64Length: applePaySessionBase64.length,
212
+ base64Preview: applePaySessionBase64.substring(0, 100) + "...",
213
+ base64End: applePaySessionBase64.substring(Math.max(0, applePaySessionBase64.length - 50))
214
+ });
215
+
216
+ // Decode Base64 to get merchant session JSON
217
+ let merchantSessionJson;
218
+ try {
219
+ merchantSessionJson = Buffer.from(applePaySessionBase64, 'base64').toString('utf-8');
220
+ strapi.log.info("[Apple Pay] Base64 decoded successfully, JSON length:", merchantSessionJson.length);
221
+ } catch (decodeError) {
222
+ strapi.log.error("[Apple Pay] Failed to decode Base64:", {
223
+ error: decodeError.message,
224
+ base64Length: applePaySessionBase64.length
225
+ });
226
+ throw new Error(`Failed to decode Base64 merchant session: ${decodeError.message}`);
227
+ }
228
+
229
+ // Parse JSON merchant session
230
+ let merchantSession;
231
+ try {
232
+ merchantSession = JSON.parse(merchantSessionJson);
233
+ strapi.log.info("[Apple Pay] Merchant session JSON parsed successfully");
234
+ } catch (parseError) {
235
+ strapi.log.error("[Apple Pay] Failed to parse merchant session JSON:", {
236
+ error: parseError.message,
237
+ jsonPreview: merchantSessionJson.substring(0, 500)
238
+ });
239
+ throw new Error(`Failed to parse merchant session JSON: ${parseError.message}`);
240
+ }
241
+
242
+ strapi.log.info("[Apple Pay] Merchant session extracted successfully:", {
243
+ hasMerchantIdentifier: !!merchantSession.merchantIdentifier,
244
+ hasEpochTimestamp: !!merchantSession.epochTimestamp,
245
+ hasExpiresAt: !!merchantSession.expiresAt,
246
+ merchantSessionKeys: Object.keys(merchantSession)
247
+ });
240
248
 
241
249
  if (merchantSession.epochTimestamp && merchantSession.epochTimestamp > 1000000000000) {
242
250
  merchantSession.epochTimestamp = Math.floor(merchantSession.epochTimestamp / 1000);
@@ -274,7 +282,9 @@ const validateApplePayMerchant = async (strapi, params) => {
274
282
  throw new Error(
275
283
  `Payone Apple Pay initialization failed: ${errorCode ? `Error ${errorCode}` : 'Unknown error'} - ${errorMessage || 'Please check your Payone Apple Pay configuration in PMI'}`
276
284
  );
285
+
277
286
  } catch (error) {
287
+ strapi.log.error("[Apple Pay] Error:", error instanceof Error ? error.message : error);
278
288
  throw error;
279
289
  }
280
290
  };
@@ -9,6 +9,31 @@ const { logTransaction } = require("./transactionService");
9
9
 
10
10
  const POST_GATEWAY_URL = "https://api.pay1.de/post-gateway/";
11
11
 
12
+ const getInvoiceIdObject = (invoiceid) => {
13
+ if (!invoiceid || typeof invoiceid !== 'string') {
14
+ return null;
15
+ }
16
+
17
+ const invoiceIdVariants = [
18
+ 'invoiceid',
19
+ 'invoiceId',
20
+ 'invoice_id',
21
+ 'invoiceID',
22
+ 'InvoiceId',
23
+ 'InvoiceID',
24
+ 'Invoice_Id',
25
+ 'INVOICEID',
26
+ 'INVOICE_ID'
27
+ ];
28
+
29
+ let invoiceIdObject = {}
30
+ for (const variant of invoiceIdVariants) {
31
+ invoiceIdObject[variant] = invoiceid;
32
+ }
33
+
34
+ return invoiceIdObject;
35
+ };
36
+
12
37
  const sendRequest = async (strapi, params) => {
13
38
  try {
14
39
  const settings = await getSettings(strapi);
@@ -87,30 +112,45 @@ const sendRequest = async (strapi, params) => {
87
112
  };
88
113
 
89
114
  const preauthorization = async (strapi, params) => {
115
+
90
116
  const requiredParams = {
91
117
  request: "preauthorization",
92
- clearingtype: params.clearingtype || "cc",
93
- amount: params.amount || 1000,
94
- currency: params.currency || "EUR",
95
- reference: params.reference || `PREAUTH-${Date.now()}`,
96
- firstname: params.firstname || "Test",
97
- lastname: params.lastname || "User",
98
- street: params.street || "Test Street 1",
99
- zip: params.zip || "12345",
100
- city: params.city || "Test City",
101
- country: params.country || "DE",
102
- email: params.email || "test@example.com",
118
+ clearingtype: params.clearingtype,
119
+ amount: params.amount,
120
+ currency: params.currency,
121
+ reference: params.reference,
122
+ firstname: params.firstname,
123
+ lastname: params.lastname,
124
+ street: params.street,
125
+ zip: params.zip,
126
+ city: params.city,
127
+ country: params.country,
128
+ email: params.email,
129
+ narrative_text: params.narrative_text,
130
+ ...getInvoiceIdObject(params.invoiceid),
103
131
  ...params
104
132
  };
105
133
 
134
+
106
135
  const updatedParams = addPaymentMethodParams(requiredParams, strapi.log);
107
136
  return await sendRequest(strapi, updatedParams);
108
137
  };
109
138
 
110
139
  const authorization = async (strapi, params) => {
140
+
111
141
  const requiredParams = {
112
142
  request: "authorization",
113
- clearingtype: params.clearingtype || "cc",
143
+ clearingtype: params.clearingtype,
144
+ reference: params.reference,
145
+ firstname: params.firstname,
146
+ lastname: params.lastname,
147
+ street: params.street,
148
+ zip: params.zip,
149
+ city: params.city,
150
+ country: params.country,
151
+ email: params.email,
152
+ narrative_text: params.narrative_text,
153
+ ...getInvoiceIdObject(params.invoiceid),
114
154
  ...params
115
155
  };
116
156
 
@@ -123,15 +163,16 @@ const capture = async (strapi, params) => {
123
163
  throw new Error("Transaction ID (txid) is required for capture");
124
164
  }
125
165
 
166
+
126
167
  const requiredParams = {
127
168
  request: "capture",
128
169
  txid: params.txid,
129
170
  amount: params.amount || 1000,
130
171
  currency: params.currency || "EUR",
172
+ ...getInvoiceIdObject(params.invoiceid),
131
173
  ...params
132
174
  };
133
175
 
134
- delete requiredParams.reference;
135
176
  return await sendRequest(strapi, requiredParams);
136
177
  };
137
178
 
@@ -140,12 +181,14 @@ const refund = async (strapi, params) => {
140
181
  throw new Error("Transaction ID (txid) is required for refund");
141
182
  }
142
183
 
184
+
143
185
  const requiredParams = {
144
186
  request: "refund",
145
187
  txid: params.txid,
146
188
  amount: params.amount || 1000,
147
189
  currency: params.currency || "EUR",
148
190
  reference: params.reference || `REFUND-${Date.now()}`,
191
+ ...getInvoiceIdObject(params.invoiceid),
149
192
  ...params
150
193
  };
151
194
 
@@ -12,6 +12,7 @@ const logTransaction = async (strapi, transactionData) => {
12
12
  timestamp: new Date().toISOString(),
13
13
  txid: transactionData.txid || null,
14
14
  reference: transactionData.reference || null,
15
+ invoiceid: transactionData.invoiceid || null,
15
16
  request_type:
16
17
  transactionData.request_type || transactionData.request || "unknown",
17
18
  amount: transactionData.amount || null,
@@ -27,6 +28,7 @@ const logTransaction = async (strapi, transactionData) => {
27
28
  transactionData.customer_message ||
28
29
  transactionData.Error?.CustomerMessage ||
29
30
  null,
31
+ body: transactionData || null,
30
32
  raw_request: transactionData.raw_request || null,
31
33
  raw_response: transactionData.raw_response || transactionData,
32
34
  created_at: new Date().toISOString(),
@@ -52,10 +54,19 @@ const getTransactionHistory = async (strapi, filters = {}) => {
52
54
  let transactionHistory =
53
55
  (await pluginStore.get({ key: "transactionHistory" })) || [];
54
56
 
55
- if (filters.status) {
56
- transactionHistory = transactionHistory.filter(
57
- (transaction) => transaction.status === filters.status
58
- );
57
+ if (filters.search) {
58
+ const searchLower = filters.search.toLowerCase().trim();
59
+ transactionHistory = transactionHistory.filter((transaction) => {
60
+ const status = (transaction.status || "").toLowerCase();
61
+ const txid = (transaction.txid || "").toLowerCase();
62
+ const reference = (transaction.reference || "").toLowerCase();
63
+
64
+ return (
65
+ status.includes(searchLower) ||
66
+ txid.includes(searchLower) ||
67
+ reference.includes(searchLower)
68
+ );
69
+ });
59
70
  }
60
71
 
61
72
  if (filters.request_type) {
@@ -64,16 +75,28 @@ const getTransactionHistory = async (strapi, filters = {}) => {
64
75
  );
65
76
  }
66
77
 
67
- if (filters.txid) {
68
- transactionHistory = transactionHistory.filter(
69
- (transaction) => transaction.txid === filters.txid
70
- );
71
- }
72
-
73
- if (filters.reference) {
74
- transactionHistory = transactionHistory.filter(
75
- (transaction) => transaction.reference === filters.reference
76
- );
78
+ if (filters.payment_method) {
79
+ transactionHistory = transactionHistory.filter((transaction) => {
80
+ const clearingtype = transaction.raw_request?.clearingtype || "";
81
+ const wallettype = transaction.raw_request?.wallettype || "";
82
+
83
+ switch (filters.payment_method) {
84
+ case "credit_card":
85
+ return clearingtype === "cc";
86
+ case "paypal":
87
+ return clearingtype === "wlt" && wallettype === "PPE";
88
+ case "google_pay":
89
+ return clearingtype === "wlt" && (wallettype === "GPY" || wallettype === "GOOGLEPAY");
90
+ case "apple_pay":
91
+ return clearingtype === "wlt" && (wallettype === "APL" || wallettype === "APPLEPAY");
92
+ case "sofort":
93
+ return clearingtype === "sb";
94
+ case "sepa":
95
+ return clearingtype === "elv";
96
+ default:
97
+ return false;
98
+ }
99
+ });
77
100
  }
78
101
 
79
102
  if (filters.date_from) {
@@ -43,6 +43,26 @@ const addPaymentMethodParams = (params, logger) => {
43
43
  const updated = { ...params };
44
44
  const clearingtype = updated.clearingtype || "cc";
45
45
 
46
+ const customParams = {};
47
+ const knownParams = new Set([
48
+ 'cardpan', 'cardexpiredate', 'cardcvc2', 'cardtype', 'wallettype',
49
+ 'bankcountry', 'iban', 'bic', 'bankaccountholder', 'onlinebanktransfertype',
50
+ 'recurrence', 'financingtype', 'invoicetype',
51
+ // Common defaults
52
+ 'salutation', 'gender', 'telephonenumber', 'ip', 'language', 'customer_is_present',
53
+ // Payment method tokens
54
+ 'applePayToken', 'googlePayToken',
55
+ // Other known params
56
+ 'clearingtype', 'paymentMethod', 'settings', 'enable3DSecure', 'ecommercemode'
57
+ ]);
58
+
59
+ // Extract custom params that are not in known params
60
+ Object.keys(updated).forEach(key => {
61
+ if (!knownParams.has(key) && !key.startsWith('add_paydata[')) {
62
+ customParams[key] = updated[key];
63
+ }
64
+ });
65
+
46
66
  const methodDefaults = {
47
67
  cc: {
48
68
  cardpan: "4111111111111111",
@@ -123,18 +143,27 @@ const addPaymentMethodParams = (params, logger) => {
123
143
  if (updated.applePayToken) {
124
144
  let tokenData;
125
145
  try {
126
- // Decode Base64 token
127
146
  const tokenString = Buffer.from(updated.applePayToken, 'base64').toString('utf-8');
128
147
  tokenData = JSON.parse(tokenString);
148
+
149
+ if (logger) {
150
+ logger.info("[Apple Pay] Token decoded from Base64 successfully");
151
+ }
129
152
  } catch (e) {
130
153
  try {
131
- // Try parsing as JSON string directly
132
154
  tokenData = typeof updated.applePayToken === 'string'
133
155
  ? JSON.parse(updated.applePayToken)
134
156
  : updated.applePayToken;
157
+
158
+ if (logger) {
159
+ logger.info("[Apple Pay] Token parsed as JSON string directly");
160
+ }
135
161
  } catch (e2) {
136
- // If already an object, use as-is
137
162
  tokenData = updated.applePayToken;
163
+
164
+ if (logger) {
165
+ logger.info("[Apple Pay] Token used as-is (already an object)");
166
+ }
138
167
  }
139
168
  }
140
169
 
@@ -143,7 +172,10 @@ const addPaymentMethodParams = (params, logger) => {
143
172
 
144
173
  if (!paymentData) {
145
174
  if (logger) {
146
- logger.error("[Apple Pay] Invalid token structure: missing paymentData field");
175
+ logger.error("[Apple Pay] Invalid token structure: missing paymentData field", {
176
+ tokenKeys: Object.keys(tokenData),
177
+ tokenStructure: JSON.stringify(tokenData).substring(0, 500)
178
+ });
147
179
  }
148
180
  delete updated.applePayToken;
149
181
  return updated;
@@ -152,30 +184,66 @@ const addPaymentMethodParams = (params, logger) => {
152
184
  const header = paymentData.header || {};
153
185
 
154
186
  // Payone required fields according to docs
155
- updated["add_paydata[paymentdata_token_version]"] = paymentData.version || "EC_v1";
156
- updated["add_paydata[paymentdata_token_data]"] = paymentData.data || "";
157
- updated["add_paydata[paymentdata_token_signature]"] = paymentData.signature || "";
158
- updated["add_paydata[paymentdata_token_ephemeral_publickey]"] = header.ephemeralPublicKey || "";
159
- updated["add_paydata[paymentdata_token_publickey_hash]"] = header.publicKeyHash || "";
187
+ // Extract version, data, signature from paymentData
188
+ const tokenVersion = paymentData.version || "EC_v1";
189
+ const tokenDataValue = paymentData.data || "";
190
+ const tokenSignature = paymentData.signature || "";
191
+
192
+ // Extract from header
193
+ const ephemeralPublicKey = header.ephemeralPublicKey || "";
194
+ const publicKeyHash = header.publicKeyHash || "";
195
+ const transactionId = paymentData.transactionId || header.transactionId || "";
196
+
197
+ // Set Payone required fields
198
+ updated["add_paydata[paymentdata_token_version]"] = tokenVersion;
199
+ updated["add_paydata[paymentdata_token_data]"] = tokenDataValue;
200
+ updated["add_paydata[paymentdata_token_signature]"] = tokenSignature;
201
+ updated["add_paydata[paymentdata_token_ephemeral_publickey]"] = ephemeralPublicKey;
202
+ updated["add_paydata[paymentdata_token_publickey_hash]"] = publicKeyHash;
160
203
 
161
204
  // Transaction ID is optional according to Payone docs
162
- if (paymentData.transactionId || header.transactionId) {
163
- updated["add_paydata[paymentdata_token_transaction_id]"] = paymentData.transactionId || header.transactionId || "";
205
+ if (transactionId) {
206
+ updated["add_paydata[paymentdata_token_transaction_id]"] = transactionId;
164
207
  }
165
208
 
166
- if (!updated["add_paydata[paymentdata_token_data]"] ||
167
- !updated["add_paydata[paymentdata_token_signature]"] ||
168
- !updated["add_paydata[paymentdata_token_ephemeral_publickey]"] ||
169
- !updated["add_paydata[paymentdata_token_publickey_hash]"]) {
209
+ if (logger) {
210
+ logger.info("[Apple Pay] Token extracted successfully:", {
211
+ hasVersion: !!tokenVersion,
212
+ hasData: !!tokenDataValue,
213
+ hasSignature: !!tokenSignature,
214
+ hasEphemeralPublicKey: !!ephemeralPublicKey,
215
+ hasPublicKeyHash: !!publicKeyHash,
216
+ hasTransactionId: !!transactionId,
217
+ dataLength: tokenDataValue.length,
218
+ signatureLength: tokenSignature.length,
219
+ ephemeralPublicKeyLength: ephemeralPublicKey.length,
220
+ publicKeyHashLength: publicKeyHash.length
221
+ });
222
+ }
223
+
224
+ // Validate required fields
225
+ if (!tokenDataValue ||
226
+ !tokenSignature ||
227
+ !ephemeralPublicKey ||
228
+ !publicKeyHash) {
170
229
  if (logger) {
171
230
  logger.error("[Apple Pay] Missing required token fields:", {
172
- hasData: !!updated["add_paydata[paymentdata_token_data]"],
173
- hasSignature: !!updated["add_paydata[paymentdata_token_signature]"],
174
- hasEphemeralPublicKey: !!updated["add_paydata[paymentdata_token_ephemeral_publickey]"],
175
- hasPublicKeyHash: !!updated["add_paydata[paymentdata_token_publickey_hash]"]
231
+ hasData: !!tokenDataValue,
232
+ hasSignature: !!tokenSignature,
233
+ hasEphemeralPublicKey: !!ephemeralPublicKey,
234
+ hasPublicKeyHash: !!publicKeyHash,
235
+ paymentDataKeys: Object.keys(paymentData),
236
+ headerKeys: Object.keys(header)
176
237
  });
177
238
  }
178
239
  }
240
+ } else {
241
+ if (logger) {
242
+ logger.error("[Apple Pay] Token is not a valid object:", {
243
+ tokenType: typeof tokenData,
244
+ tokenValue: typeof tokenData === 'string' ? tokenData.substring(0, 200) : String(tokenData).substring(0, 200)
245
+ });
246
+ }
179
247
  }
180
248
 
181
249
  delete updated.applePayToken;
@@ -210,6 +278,8 @@ const addPaymentMethodParams = (params, logger) => {
210
278
  }
211
279
  });
212
280
 
281
+ Object.assign(updated, customParams);
282
+
213
283
  return updated;
214
284
  };
215
285