strapi-plugin-payone-provider 1.4.2 → 1.5.0

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,261 @@
1
+ "use strict";
2
+
3
+ const axios = require("axios");
4
+ const { buildClientRequestParams, toFormData } = require("../utils/requestBuilder");
5
+ const { getSettings, validateSettings } = require("./settingsService");
6
+
7
+ const POST_GATEWAY_URL = "https://api.pay1.de/post-gateway/";
8
+
9
+ /**
10
+ * Initialize Apple Pay session with Payone
11
+ * According to Payone documentation:
12
+ * https://docs.payone.com/payment-methods/apple-pay/apple-pay-without-dev
13
+ *
14
+ * Request: genericpayment
15
+ * Required parameters:
16
+ * - request="genericpayment"
17
+ * - clearingtype="wlt"
18
+ * - wallettype="APL"
19
+ * - add_paydata[action]="init_applepay_session"
20
+ * - add_paydata[display_name]="Store Name"
21
+ * - add_paydata[domain_name]="yourdomain.com"
22
+ */
23
+ const initializeApplePaySession = async (strapi, params) => {
24
+ try {
25
+ strapi.log.info("[Apple Pay] Initializing Apple Pay session with Payone");
26
+ strapi.log.info("[Apple Pay] Request params:", JSON.stringify(params, null, 2));
27
+
28
+ const settings = await getSettings(strapi);
29
+
30
+ if (!validateSettings(settings)) {
31
+ strapi.log.error("[Apple Pay] Payone settings not configured");
32
+ throw new Error("Payone settings not configured");
33
+ }
34
+
35
+ strapi.log.info("[Apple Pay] Settings loaded:", {
36
+ mode: settings.mode,
37
+ mid: settings.mid,
38
+ portalid: settings.portalid,
39
+ hasKey: !!settings.key
40
+ });
41
+
42
+ const {
43
+ displayName,
44
+ domainName,
45
+ mid,
46
+ portalid
47
+ } = params;
48
+
49
+ // Get merchant data from settings (test or live mode)
50
+ const merchantName = displayName || settings.merchantName || settings.displayName || "Test Store";
51
+ const merchantId = mid || settings.mid || settings.merchantIdentifier;
52
+ const portalId = portalid || settings.portalid;
53
+ const accountId = settings.aid;
54
+ const apiKey = settings.key;
55
+ const mode = settings.mode || "test"; // test or live
56
+
57
+ // Get domain from params or settings or server config
58
+ const domain = domainName || settings.domainName ||
59
+ (strapi.config.get("server.url") ? new URL(strapi.config.get("server.url")).hostname : null) ||
60
+ "localhost";
61
+
62
+ // Build request parameters for Apple Pay session initialization
63
+ // According to Payone documentation: request="genericpayment"
64
+ const requestParams = {
65
+ request: "genericpayment",
66
+ mid: merchantId,
67
+ aid: accountId,
68
+ portalid: portalId,
69
+ key: apiKey,
70
+ mode: mode, // Use test or live mode from settings
71
+ clearingtype: "wlt",
72
+ wallettype: "APL",
73
+ currency: "EUR", // Default, can be overridden
74
+ "add_paydata[action]": "init_applepay_session",
75
+ "add_paydata[display_name]": merchantName,
76
+ "add_paydata[domain_name]": domain
77
+ };
78
+
79
+ strapi.log.info("[Apple Pay] Sending request to Payone:", {
80
+ url: POST_GATEWAY_URL,
81
+ mode: mode,
82
+ merchantName: merchantName,
83
+ domain: domain,
84
+ merchantId: merchantId,
85
+ portalId: portalId
86
+ });
87
+
88
+ const formData = toFormData(requestParams);
89
+
90
+ const response = await axios.post(POST_GATEWAY_URL, formData, {
91
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
92
+ timeout: 30000
93
+ });
94
+
95
+ strapi.log.info("[Apple Pay] Payone response received:", {
96
+ status: response.status,
97
+ statusText: response.statusText
98
+ });
99
+
100
+ // Parse response
101
+ const responseData = parseResponse(response.data, strapi.log);
102
+
103
+ strapi.log.info("[Apple Pay] Session initialization response:", JSON.stringify(responseData, null, 2));
104
+ strapi.log.info("[Apple Pay] Response status:", responseData.status || responseData.Status);
105
+
106
+ if (responseData.errorcode || responseData.ErrorCode) {
107
+ strapi.log.warn("[Apple Pay] Response contains error:", {
108
+ errorcode: responseData.errorcode || responseData.ErrorCode,
109
+ errormessage: responseData.errormessage || responseData.ErrorMessage
110
+ });
111
+ }
112
+
113
+ return responseData;
114
+ } catch (error) {
115
+ strapi.log.error("[Apple Pay] Session initialization error:", {
116
+ message: error.message,
117
+ stack: error.stack,
118
+ response: error.response?.data
119
+ });
120
+ throw error;
121
+ }
122
+ };
123
+
124
+ /**
125
+ * Validate Apple Pay merchant with Payone
126
+ * This is called when Apple Pay requests merchant validation
127
+ */
128
+ const validateApplePayMerchant = async (strapi, params) => {
129
+ try {
130
+ strapi.log.info("[Apple Pay] Validating merchant with Payone");
131
+ strapi.log.info("[Apple Pay] Validation params:", JSON.stringify({
132
+ validationURL: params.validationURL,
133
+ domain: params.domain,
134
+ displayName: params.displayName,
135
+ mid: params.mid,
136
+ portalid: params.portalid
137
+ }, null, 2));
138
+
139
+ const settings = await getSettings(strapi);
140
+
141
+ if (!validateSettings(settings)) {
142
+ strapi.log.error("[Apple Pay] Payone settings not configured for merchant validation");
143
+ throw new Error("Payone settings not configured");
144
+ }
145
+
146
+ const {
147
+ validationURL,
148
+ mid,
149
+ portalid,
150
+ domain,
151
+ displayName
152
+ } = params;
153
+
154
+ // Get merchant data from settings (test or live mode)
155
+ const merchantName = displayName || settings.merchantName || settings.displayName || "Test Store";
156
+ const merchantId = mid || settings.mid || settings.merchantIdentifier;
157
+ const portalId = portalid || settings.portalid;
158
+
159
+ // Get domain from params or settings or server config
160
+ const domainName = domain || settings.domainName ||
161
+ (strapi.config.get("server.url") ? new URL(strapi.config.get("server.url")).hostname : null) ||
162
+ "localhost";
163
+
164
+ // For Payone integration without developer account,
165
+ // Payone handles merchant validation
166
+ // We need to initialize the session first
167
+ const sessionParams = {
168
+ displayName: merchantName,
169
+ domainName: domainName,
170
+ mid: merchantId,
171
+ portalid: portalId
172
+ };
173
+
174
+ strapi.log.info("[Apple Pay] Initializing session with params:", JSON.stringify(sessionParams, null, 2));
175
+
176
+ // Initialize Apple Pay session with Payone
177
+ const sessionResponse = await initializeApplePaySession(strapi, sessionParams);
178
+
179
+ strapi.log.info("[Apple Pay] Session initialization result:", {
180
+ status: sessionResponse.status || sessionResponse.Status,
181
+ hasMerchantIdentifier: !!(sessionResponse.merchantIdentifier || sessionResponse.merchantSessionIdentifier)
182
+ });
183
+
184
+ // If session initialization is successful, return merchant session
185
+ // Payone will provide the merchant identifier and validation data
186
+ if (sessionResponse.status === "APPROVED" || sessionResponse.status === "REDIRECT") {
187
+ strapi.log.info("[Apple Pay] Session approved, creating merchant session object");
188
+ // Get merchant identifier from Payone response or settings
189
+ const merchantIdentifier = sessionResponse.merchantIdentifier ||
190
+ sessionResponse.merchantSessionIdentifier ||
191
+ settings.merchantIdentifier ||
192
+ settings.mid ||
193
+ settings.portalid ||
194
+ `merchant.${domainName}`;
195
+
196
+ // Return merchant session object
197
+ // In a real implementation, you would get this from Payone's response
198
+ const merchantSession = {
199
+ epochTimestamp: Date.now(),
200
+ expiresAt: Date.now() + (5 * 60 * 1000), // 5 minutes
201
+ merchantSessionIdentifier: sessionResponse.merchantSessionIdentifier || `merchant.${domainName}`,
202
+ nonce: sessionResponse.nonce || generateNonce(),
203
+ merchantIdentifier: merchantIdentifier,
204
+ domainName: domainName,
205
+ displayName: merchantName
206
+ };
207
+
208
+ strapi.log.info("[Apple Pay] Merchant session created:", {
209
+ merchantIdentifier: merchantSession.merchantIdentifier,
210
+ domainName: merchantSession.domainName,
211
+ expiresAt: new Date(merchantSession.expiresAt).toISOString()
212
+ });
213
+
214
+ return merchantSession;
215
+ }
216
+
217
+ // If initialization failed, return empty object
218
+ // Payment Request API will handle it
219
+ strapi.log.warn("[Apple Pay] Session initialization failed, returning empty object");
220
+ return {};
221
+ } catch (error) {
222
+ strapi.log.error("[Apple Pay] Merchant validation error:", {
223
+ message: error.message,
224
+ stack: error.stack,
225
+ response: error.response?.data
226
+ });
227
+ // Return empty object on error - Payone will handle validation
228
+ return {};
229
+ }
230
+ };
231
+
232
+ /**
233
+ * Parse Payone response
234
+ */
235
+ const parseResponse = (responseData, logger) => {
236
+ if (typeof responseData === 'string') {
237
+ // Parse form-encoded response
238
+ const params = new URLSearchParams(responseData);
239
+ const parsed = {};
240
+ for (const [key, value] of params.entries()) {
241
+ parsed[key] = value;
242
+ }
243
+ return parsed;
244
+ }
245
+ return responseData;
246
+ };
247
+
248
+ /**
249
+ * Generate nonce for merchant session
250
+ */
251
+ const generateNonce = () => {
252
+ return Math.random().toString(36).substring(2, 15) +
253
+ Math.random().toString(36).substring(2, 15);
254
+ };
255
+
256
+ module.exports = {
257
+ initializeApplePaySession,
258
+ validateApplePayMerchant
259
+ };
260
+
261
+
@@ -4,6 +4,7 @@ const settingsService = require("./settingsService");
4
4
  const transactionService = require("./transactionService");
5
5
  const paymentService = require("./paymentService");
6
6
  const testConnectionService = require("./testConnectionService");
7
+ const applePayService = require("./applePayService");
7
8
 
8
9
  /**
9
10
  * Main Payone service - aggregates all sub-services
@@ -52,5 +53,14 @@ module.exports = ({ strapi }) => ({
52
53
  // 3D Secure callback handler
53
54
  async handle3DSCallback(callbackData, resultType) {
54
55
  return await paymentService.handle3DSCallback(strapi, callbackData, resultType);
56
+ },
57
+
58
+ // Apple Pay
59
+ async validateApplePayMerchant(params) {
60
+ return await applePayService.validateApplePayMerchant(strapi, params);
61
+ },
62
+
63
+ async initializeApplePaySession(params) {
64
+ return await applePayService.initializeApplePaySession(strapi, params);
55
65
  }
56
66
  });
@@ -84,11 +84,28 @@ const addPaymentMethodParams = (params, logger) => {
84
84
  }
85
85
  });
86
86
 
87
+ // Handle Apple Pay token if present
88
+ if (updated.applePayToken || updated["add_paydata[paymentmethod_token_data]"]) {
89
+ const token = updated.applePayToken || updated["add_paydata[paymentmethod_token_data]"];
90
+ const gatewayMerchantId = updated.mid || updated.portalid || '';
91
+
92
+ updated["add_paydata[paymentmethod_token_data]"] = token;
93
+ updated["add_paydata[paymentmethod]"] = "APL";
94
+ updated["add_paydata[paymentmethod_type]"] = "APPLEPAY";
95
+ updated["add_paydata[gatewayid]"] = "payonegmbh";
96
+ if (gatewayMerchantId) {
97
+ updated["add_paydata[gateway_merchantid]"] = gatewayMerchantId;
98
+ }
99
+
100
+ // Remove applePayToken from params as it's now in add_paydata
101
+ delete updated.applePayToken;
102
+ }
103
+
87
104
  // Ensure wallettype is set for wallet payments
88
105
  if (updated.clearingtype === "wlt" && !updated.wallettype) {
89
- if (clearingtype === "gpp" || updated.paymentMethod === "gpp" || updated["add_paydata[paymentmethod_token_data]"]) {
106
+ if (clearingtype === "gpp" || updated.paymentMethod === "gpp" || (updated["add_paydata[paymentmethod]"] === "GGP")) {
90
107
  updated.wallettype = "GGP";
91
- } else if (clearingtype === "apl" || updated.paymentMethod === "apl") {
108
+ } else if (clearingtype === "apl" || updated.paymentMethod === "apl" || (updated["add_paydata[paymentmethod]"] === "APL")) {
92
109
  updated.wallettype = "APL";
93
110
  } else {
94
111
  updated.wallettype = "PPE";