@cloudcommerce/app-paypal 2.48.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.
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/assets/onload-expression.js +60 -0
- package/assets/onload-expression.min.js +1 -0
- package/events.js +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -0
- package/lib/paypal-create-transaction.d.ts +83 -0
- package/lib/paypal-create-transaction.js +262 -0
- package/lib/paypal-create-transaction.js.map +1 -0
- package/lib/paypal-events.d.ts +5 -0
- package/lib/paypal-events.js +117 -0
- package/lib/paypal-events.js.map +1 -0
- package/lib/paypal-list-payments.d.ts +11 -0
- package/lib/paypal-list-payments.js +216 -0
- package/lib/paypal-list-payments.js.map +1 -0
- package/lib/paypal.d.ts +92 -0
- package/lib/paypal.js +12 -0
- package/lib/paypal.js.map +1 -0
- package/lib/util/parse-to-paypal-payment.d.ts +33 -0
- package/lib/util/parse-to-paypal-payment.js +100 -0
- package/lib/util/parse-to-paypal-payment.js.map +1 -0
- package/lib/util/paypal-api.d.ts +11 -0
- package/lib/util/paypal-api.js +149 -0
- package/lib/util/paypal-api.js.map +1 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 E-Com Club Softwares para E-commerce <ti@e-com.club>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# `@cloudcommerce/app-paypal`
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
(function paypalOnload() {
|
|
2
|
+
window._pppContinue = new Promise((resolve, reject) => {
|
|
3
|
+
// https://developer.paypal.com
|
|
4
|
+
// /docs/integration/paypal-plus/mexico-brazil/integrate-a-payment-selection-page/
|
|
5
|
+
const pppParams = {
|
|
6
|
+
approvalUrl: window._paypalApprovalUrl,
|
|
7
|
+
disallowRememberedCards: Boolean(window._paypalDisallowRemembered),
|
|
8
|
+
placeholder: 'ppplus',
|
|
9
|
+
mode: window._paypalEnv,
|
|
10
|
+
disableContinue: 'pppContinue',
|
|
11
|
+
enableContinue: 'pppContinue',
|
|
12
|
+
onContinue(rememberedCards, payerId, paymentId) {
|
|
13
|
+
resolve({
|
|
14
|
+
credit_card: {
|
|
15
|
+
token: rememberedCards || '',
|
|
16
|
+
},
|
|
17
|
+
intermediator_buyer_id: payerId,
|
|
18
|
+
open_payment_id: window._paypalPaymentId
|
|
19
|
+
+ '/' + paymentId
|
|
20
|
+
+ '/' + window._paypalInvoiceNumber,
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
onError(err) {
|
|
24
|
+
reject(err);
|
|
25
|
+
},
|
|
26
|
+
onLoad() {
|
|
27
|
+
const $loading = document.getElementById('pppLoading');
|
|
28
|
+
if ($loading) {
|
|
29
|
+
$loading.remove();
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
if (window.storefrontApp) {
|
|
35
|
+
const customer = window.storefrontApp.customer;
|
|
36
|
+
if (customer) {
|
|
37
|
+
pppParams.payerEmail = customer.main_email;
|
|
38
|
+
pppParams.payerTaxId = customer.doc_number;
|
|
39
|
+
pppParams.payerTaxIdType = customer.registry_type === 'j' ? 'BR_CNPJ' : 'BR_CPF';
|
|
40
|
+
pppParams.country = customer.doc_country || 'BR';
|
|
41
|
+
if (pppParams.country === 'BR') {
|
|
42
|
+
pppParams.language = 'pt_BR';
|
|
43
|
+
}
|
|
44
|
+
if (customer.name && customer.name.given_name) {
|
|
45
|
+
pppParams.payerFirstName = customer.name.given_name;
|
|
46
|
+
if (customer.name.middle_name && customer.name.family_name) {
|
|
47
|
+
pppParams.payerLastName = customer.name.middle_name + ' ' + customer.name.family_name;
|
|
48
|
+
} else if (customer.name.middle_name || customer.name.family_name) {
|
|
49
|
+
pppParams.payerLastName = customer.name.middle_name || customer.name.family_name;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (Array.isArray(customer.phones) && customer.phones[0]) {
|
|
53
|
+
pppParams.payerPhone = customer.phones[0].number.toString();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
window._pppApp = window.PAYPAL.apps.PPP(pppParams);
|
|
59
|
+
});
|
|
60
|
+
}());
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
window._pppContinue=new Promise((p,a)=>{var e,n={approvalUrl:window._paypalApprovalUrl,disallowRememberedCards:Boolean(window._paypalDisallowRemembered),placeholder:"ppplus",mode:window._paypalEnv,disableContinue:"pppContinue",enableContinue:"pppContinue",onContinue(e,a,n){p({credit_card:{token:e||""},intermediator_buyer_id:a,open_payment_id:window._paypalPaymentId+"/"+n+"/"+window._paypalInvoiceNumber})},onError(e){a(e)},onLoad(){var e=document.getElementById("pppLoading");e&&e.remove()}};window.storefrontApp&&(e=window.storefrontApp.customer)&&(n.payerEmail=e.main_email,n.payerTaxId=e.doc_number,n.payerTaxIdType="j"===e.registry_type?"BR_CNPJ":"BR_CPF",n.country=e.doc_country||"BR","BR"===n.country&&(n.language="pt_BR"),e.name&&e.name.given_name&&(n.payerFirstName=e.name.given_name,e.name.middle_name&&e.name.family_name?n.payerLastName=e.name.middle_name+" "+e.name.family_name:(e.name.middle_name||e.name.family_name)&&(n.payerLastName=e.name.middle_name||e.name.family_name)),Array.isArray(e.phones))&&e.phones[0]&&(n.payerPhone=e.phones[0].number.toString()),window._pppApp=window.PAYPAL.apps.PPP(n)});
|
package/events.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/paypal-events.js';
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './paypal';
|
package/lib/index.js
ADDED
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { AppModuleBody } from '@cloudcommerce/types';
|
|
2
|
+
declare const _default: (modBody: AppModuleBody<"create_transaction">) => Promise<{
|
|
3
|
+
error: string;
|
|
4
|
+
message: string;
|
|
5
|
+
status?: undefined;
|
|
6
|
+
transaction?: undefined;
|
|
7
|
+
} | {
|
|
8
|
+
status: number;
|
|
9
|
+
error: string;
|
|
10
|
+
message: string;
|
|
11
|
+
transaction?: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
transaction: {
|
|
14
|
+
payment_link?: string;
|
|
15
|
+
payment_instructions?: string;
|
|
16
|
+
intermediator?: {
|
|
17
|
+
transaction_id?: string;
|
|
18
|
+
transaction_code?: string;
|
|
19
|
+
transaction_reference?: string;
|
|
20
|
+
payment_method?: {
|
|
21
|
+
code: string;
|
|
22
|
+
name?: string;
|
|
23
|
+
};
|
|
24
|
+
buyer_id?: string;
|
|
25
|
+
};
|
|
26
|
+
credit_card?: {
|
|
27
|
+
holder_name?: string;
|
|
28
|
+
avs_result_code?: string | null;
|
|
29
|
+
cvv_result_code?: string | null;
|
|
30
|
+
bin?: number;
|
|
31
|
+
company?: string;
|
|
32
|
+
last_digits?: string;
|
|
33
|
+
token?: string;
|
|
34
|
+
error_code?: "incorrect_number" | "invalid_number" | "invalid_expiry_date" | "invalid_cvc" | "expired_card" | "incorrect_cvc" | "incorrect_zip" | "incorrect_address" | "card_declined" | "processing_error" | "call_issuer" | "pick_up_card";
|
|
35
|
+
};
|
|
36
|
+
banking_billet?: {
|
|
37
|
+
code?: string;
|
|
38
|
+
valid_thru?: string;
|
|
39
|
+
text_lines?: string[];
|
|
40
|
+
link?: string;
|
|
41
|
+
};
|
|
42
|
+
loyalty_points?: {
|
|
43
|
+
name?: string;
|
|
44
|
+
program_id: string;
|
|
45
|
+
points_value: number;
|
|
46
|
+
ratio?: number;
|
|
47
|
+
};
|
|
48
|
+
account_deposit?: {
|
|
49
|
+
valid_thru?: string;
|
|
50
|
+
text_lines?: string[];
|
|
51
|
+
};
|
|
52
|
+
currency_id?: string;
|
|
53
|
+
currency_symbol?: string;
|
|
54
|
+
discount?: number;
|
|
55
|
+
amount: number;
|
|
56
|
+
installments?: {
|
|
57
|
+
number: number;
|
|
58
|
+
value?: number;
|
|
59
|
+
tax?: boolean;
|
|
60
|
+
total?: number;
|
|
61
|
+
};
|
|
62
|
+
creditor_fees?: {
|
|
63
|
+
installment?: number;
|
|
64
|
+
operational?: number;
|
|
65
|
+
intermediation?: number;
|
|
66
|
+
other?: number;
|
|
67
|
+
};
|
|
68
|
+
status?: {
|
|
69
|
+
updated_at?: string;
|
|
70
|
+
current: "pending" | "under_analysis" | "authorized" | "unauthorized" | "paid" | "in_dispute" | "refunded" | "voided" | "unknown";
|
|
71
|
+
};
|
|
72
|
+
flags?: string[];
|
|
73
|
+
custom_fields?: {
|
|
74
|
+
field: string;
|
|
75
|
+
value: string;
|
|
76
|
+
}[];
|
|
77
|
+
notes?: string;
|
|
78
|
+
};
|
|
79
|
+
error?: undefined;
|
|
80
|
+
message?: undefined;
|
|
81
|
+
status?: undefined;
|
|
82
|
+
}>;
|
|
83
|
+
export default _default;
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { logger } from '@cloudcommerce/firebase/lib/config';
|
|
2
|
+
import parseToPaypalPayment from './util/parse-to-paypal-payment.js';
|
|
3
|
+
import { readPaypalPayment, editPaypalPayment, executePaypalPayment } from './util/paypal-api.js';
|
|
4
|
+
|
|
5
|
+
export default async (modBody) => {
|
|
6
|
+
const { application, params } = modBody;
|
|
7
|
+
const appData = {
|
|
8
|
+
...application.data,
|
|
9
|
+
...application.hidden_data,
|
|
10
|
+
};
|
|
11
|
+
if (appData.paypal_client_id) {
|
|
12
|
+
process.env.PAYPAL_CLIENT_ID = appData.paypal_client_id;
|
|
13
|
+
}
|
|
14
|
+
if (appData.paypal_secret) {
|
|
15
|
+
process.env.PAYPAL_CLIENT_SECRET = appData.paypal_secret;
|
|
16
|
+
}
|
|
17
|
+
process.env.PAYPAL_ENV = appData.paypal_sandbox
|
|
18
|
+
? 'sandbox'
|
|
19
|
+
: process.env.PAYPAL_ENV || 'live';
|
|
20
|
+
const { PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET } = process.env;
|
|
21
|
+
if (!PAYPAL_CLIENT_ID || !PAYPAL_CLIENT_SECRET) {
|
|
22
|
+
return {
|
|
23
|
+
error: 'NO_PAYPAL_KEYS',
|
|
24
|
+
message: 'Client ID ou Secret não configurado (lojista deve configurar o aplicativo)',
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const { order_id: orderId } = params;
|
|
28
|
+
const paypalPayerId = params.intermediator_buyer_id;
|
|
29
|
+
let paypalPaymentId;
|
|
30
|
+
let paypalOrderId;
|
|
31
|
+
let paypalInvoiceNumber;
|
|
32
|
+
let paypalPayment;
|
|
33
|
+
if (paypalPayerId && params.open_payment_id) {
|
|
34
|
+
const paymentIdParts = params.open_payment_id.split('/');
|
|
35
|
+
paypalPaymentId = paymentIdParts[0];
|
|
36
|
+
paypalOrderId = paymentIdParts[1];
|
|
37
|
+
paypalInvoiceNumber = paymentIdParts[2];
|
|
38
|
+
if (paypalPaymentId && paypalOrderId) {
|
|
39
|
+
// Must read payment before execute to get installments info
|
|
40
|
+
let initialPaypalPayment;
|
|
41
|
+
const mergePaypalPayment = {};
|
|
42
|
+
try {
|
|
43
|
+
initialPaypalPayment = await readPaypalPayment(paypalPaymentId);
|
|
44
|
+
if (initialPaypalPayment) {
|
|
45
|
+
['credit_financing_offered'].forEach((paymentProp) => {
|
|
46
|
+
mergePaypalPayment[paymentProp] = initialPaypalPayment[paymentProp];
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
} catch (_err) {
|
|
50
|
+
logger.warn(_err);
|
|
51
|
+
}
|
|
52
|
+
// https://developer.paypal.com
|
|
53
|
+
// /docs/integration/paypal-plus/mexico-brazil/test-your-integration-and-execute-the-payment/
|
|
54
|
+
const round = (n) => (n ? Math.round(n * 100) / 100 : 0);
|
|
55
|
+
const total = round(params.amount.total);
|
|
56
|
+
let subtotal = 0;
|
|
57
|
+
let isPaymentUptodate = false;
|
|
58
|
+
try {
|
|
59
|
+
const { amount } = initialPaypalPayment.transactions[0];
|
|
60
|
+
subtotal = round(Number(amount.details.subtotal));
|
|
61
|
+
if (amount.total) {
|
|
62
|
+
const amountDiff = total - round(Number(amount.total));
|
|
63
|
+
if (!amountDiff || round(Math.abs(amountDiff)) <= 0.02) {
|
|
64
|
+
// Ignore round diff
|
|
65
|
+
isPaymentUptodate = true;
|
|
66
|
+
} else {
|
|
67
|
+
// Try to update payment amount before execute
|
|
68
|
+
const createPaymentBody = parseToPaypalPayment(params);
|
|
69
|
+
const paypalPaymentEdit = [{
|
|
70
|
+
op: 'replace',
|
|
71
|
+
path: '/transactions/0/amount',
|
|
72
|
+
value: createPaymentBody.transactions[0].amount,
|
|
73
|
+
}, {
|
|
74
|
+
op: 'replace',
|
|
75
|
+
path: '/transactions/0/item_list/items',
|
|
76
|
+
value: createPaymentBody.transactions[0].item_list.items,
|
|
77
|
+
}];
|
|
78
|
+
await editPaypalPayment(paypalPaymentId, paypalPaymentEdit);
|
|
79
|
+
isPaymentUptodate = true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} catch {
|
|
83
|
+
subtotal = round(params.amount.subtotal);
|
|
84
|
+
}
|
|
85
|
+
const tryExecute = async () => {
|
|
86
|
+
const paypalPaymentExecute = {
|
|
87
|
+
payer_id: paypalPayerId,
|
|
88
|
+
};
|
|
89
|
+
if (!isPaymentUptodate) {
|
|
90
|
+
// Must specify execution amount
|
|
91
|
+
const freight = round(params.amount.freight);
|
|
92
|
+
const fixedSubtotal = subtotal + freight <= total ? subtotal : total - freight;
|
|
93
|
+
paypalPaymentExecute.transactions = [{
|
|
94
|
+
amount: {
|
|
95
|
+
total: total.toFixed(2),
|
|
96
|
+
currency: params.currency_id || 'BRL',
|
|
97
|
+
details: {
|
|
98
|
+
subtotal: fixedSubtotal.toFixed(2),
|
|
99
|
+
shipping: freight.toFixed(2),
|
|
100
|
+
tax: (total - fixedSubtotal - freight).toFixed(2),
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
}];
|
|
104
|
+
}
|
|
105
|
+
logger.info(`Executing ${paypalPaymentId} for ${orderId}`);
|
|
106
|
+
let executedPaypalPayment;
|
|
107
|
+
try {
|
|
108
|
+
executedPaypalPayment = await executePaypalPayment(paypalPaymentId, paypalPaymentExecute);
|
|
109
|
+
} catch (_err) {
|
|
110
|
+
const err = _err;
|
|
111
|
+
logger.warn(`Failed executing payment ${paypalPaymentId} for ${orderId}`, {
|
|
112
|
+
request: err.config?.data,
|
|
113
|
+
status: err.response?.status,
|
|
114
|
+
response: err.response?.data,
|
|
115
|
+
});
|
|
116
|
+
let shouldRetry = false;
|
|
117
|
+
if (err.response?.data?.name === 'INVALID_PAYER_ID') {
|
|
118
|
+
// Check payer ID from original payment
|
|
119
|
+
const paypalPayer = initialPaypalPayment?.payer || mergePaypalPayment.payer;
|
|
120
|
+
const initialPayerId = paypalPayer?.payer_info?.payer_id;
|
|
121
|
+
if (initialPayerId && initialPayerId !== paypalPayerId) {
|
|
122
|
+
paypalPaymentExecute.payer_id = initialPayerId;
|
|
123
|
+
shouldRetry = true;
|
|
124
|
+
}
|
|
125
|
+
} else if (paypalPaymentExecute.transactions?.[0]?.amount?.details) {
|
|
126
|
+
// Retry without transaction amount details (optional)
|
|
127
|
+
delete paypalPaymentExecute.transactions[0].amount.details;
|
|
128
|
+
shouldRetry = true;
|
|
129
|
+
}
|
|
130
|
+
if (shouldRetry) {
|
|
131
|
+
executedPaypalPayment = await new Promise((resolve, reject) => {
|
|
132
|
+
setTimeout(() => {
|
|
133
|
+
executePaypalPayment(paypalPaymentId, paypalPaymentExecute)
|
|
134
|
+
.then(resolve).catch(reject);
|
|
135
|
+
}, 300);
|
|
136
|
+
});
|
|
137
|
+
} else {
|
|
138
|
+
throw err;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
paypalPayment = {
|
|
142
|
+
...executedPaypalPayment,
|
|
143
|
+
...mergePaypalPayment,
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
await tryExecute().catch((_err) => {
|
|
147
|
+
const err = _err;
|
|
148
|
+
const paypalError = err.response?.data?.name;
|
|
149
|
+
if (paypalError === 'INSTRUMENT_DECLINED') {
|
|
150
|
+
logger.warn(`INSTRUMENT_DECLINED ${paypalPaymentId} for ${orderId}`);
|
|
151
|
+
} else {
|
|
152
|
+
const error = new Error('PayPal execute with error');
|
|
153
|
+
error.request = err.config?.data;
|
|
154
|
+
error.response = err.response?.data;
|
|
155
|
+
error.status = err.response?.status;
|
|
156
|
+
error.initialPaypalPayment = initialPaypalPayment;
|
|
157
|
+
error.isPaymentUptodate = isPaymentUptodate;
|
|
158
|
+
error.amount = params.amount;
|
|
159
|
+
error.subtotal = subtotal;
|
|
160
|
+
logger.error(error);
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
status: 400,
|
|
164
|
+
error: `PAYPAL_${paypalError}`,
|
|
165
|
+
message: err.message,
|
|
166
|
+
};
|
|
167
|
+
});
|
|
168
|
+
} else {
|
|
169
|
+
return {
|
|
170
|
+
status: 400,
|
|
171
|
+
error: 'PAYPAL_PAYMENT_UNKNOWN',
|
|
172
|
+
message: 'Unknown PayPal Payment/Order IDs',
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
paypalOrderId = params.open_payment_id;
|
|
177
|
+
}
|
|
178
|
+
logger.info(`New PayPal order ${paypalOrderId} for ${orderId}`);
|
|
179
|
+
if (paypalPayment) {
|
|
180
|
+
let amount;
|
|
181
|
+
let transactionCode;
|
|
182
|
+
let paymentLink;
|
|
183
|
+
let paymentReference;
|
|
184
|
+
let saleStatus = 'under_analysis';
|
|
185
|
+
if (Array.isArray(paypalPayment.transactions)) {
|
|
186
|
+
const paypalTransaction = paypalPayment.transactions[0];
|
|
187
|
+
if (paypalTransaction) {
|
|
188
|
+
// PayPal Plus executed payment
|
|
189
|
+
const paypalSale = Array.isArray(paypalTransaction.related_resources)
|
|
190
|
+
&& paypalTransaction.related_resources[0]
|
|
191
|
+
&& paypalTransaction.related_resources[0].sale;
|
|
192
|
+
saleStatus = paypalSale && (paypalSale.state === 'completed')
|
|
193
|
+
? 'paid'
|
|
194
|
+
: 'under_analysis';
|
|
195
|
+
paymentReference = paypalOrderId;
|
|
196
|
+
transactionCode = paypalSale ? paypalSale.id : paymentReference;
|
|
197
|
+
amount = paypalTransaction.amount && parseFloat(paypalTransaction.amount.total);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (amount && amount >= params.amount.total * 0.975) {
|
|
201
|
+
const transaction = {
|
|
202
|
+
amount,
|
|
203
|
+
intermediator: {
|
|
204
|
+
transaction_id: paypalPayment.id,
|
|
205
|
+
transaction_code: transactionCode,
|
|
206
|
+
},
|
|
207
|
+
status: {
|
|
208
|
+
current: saleStatus,
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
if (paymentLink) {
|
|
212
|
+
transaction.payment_link = paymentLink;
|
|
213
|
+
}
|
|
214
|
+
const transactionReference = paypalInvoiceNumber || paymentReference;
|
|
215
|
+
if (transactionReference) {
|
|
216
|
+
transaction.intermediator.transaction_reference = transactionReference;
|
|
217
|
+
}
|
|
218
|
+
const creditFinancing = paypalPayment.credit_financing_offered;
|
|
219
|
+
if (creditFinancing && creditFinancing.term) {
|
|
220
|
+
transaction.installments = {
|
|
221
|
+
number: creditFinancing.term,
|
|
222
|
+
tax: false,
|
|
223
|
+
};
|
|
224
|
+
['monthly_payment', 'total_cost'].forEach((creditFinancingProp) => {
|
|
225
|
+
if (creditFinancing[creditFinancingProp]) {
|
|
226
|
+
const value = parseFloat(creditFinancing[creditFinancingProp].value);
|
|
227
|
+
if (value) {
|
|
228
|
+
const installmentsProp = creditFinancingProp === 'total_cost'
|
|
229
|
+
? 'total' : 'value';
|
|
230
|
+
transaction.installments[installmentsProp] = value;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
if (params.amount.total && params.amount.total !== amount) {
|
|
236
|
+
// Save received amount on custom fields just for debug
|
|
237
|
+
transaction.custom_fields = transaction.custom_fields || [];
|
|
238
|
+
Object.keys(params.amount).forEach((amountField) => {
|
|
239
|
+
if (typeof params.amount[amountField] === 'number') {
|
|
240
|
+
if (transaction.custom_fields.length >= 10) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
transaction.custom_fields.push({
|
|
244
|
+
field: `pr_amount_${amountField}`,
|
|
245
|
+
value: params.amount[amountField].toString(),
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
return { transaction };
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
error: 'PAYPAL_TRANSACTION_INVALID',
|
|
254
|
+
message: 'PayPal order ID not valid for this create transaction request',
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
error: 'PAYPAL_TRANSACTION_NOOP',
|
|
259
|
+
message: `No valid PayPal response for #${orderId}`,
|
|
260
|
+
};
|
|
261
|
+
};
|
|
262
|
+
// # sourceMappingURL=paypal-create-transaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paypal-create-transaction.js","sourceRoot":"","sources":["../src/paypal-create-transaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import api from '@cloudcommerce/api';
|
|
2
|
+
import '@cloudcommerce/firebase/lib/init';
|
|
3
|
+
import * as functions from 'firebase-functions/v1';
|
|
4
|
+
import config, { logger } from '@cloudcommerce/firebase/lib/config';
|
|
5
|
+
import getAppData from '@cloudcommerce/firebase/lib/helpers/get-app-data';
|
|
6
|
+
import { readPaypalWebhookEvent } from './util/paypal-api.js';
|
|
7
|
+
|
|
8
|
+
const { httpsFunctionOptions } = config.get();
|
|
9
|
+
|
|
10
|
+
export const paypal = {
|
|
11
|
+
webhook: functions
|
|
12
|
+
.region(httpsFunctionOptions.region)
|
|
13
|
+
.runWith(httpsFunctionOptions)
|
|
14
|
+
.https.onRequest(async (req, res) => {
|
|
15
|
+
const { body } = req;
|
|
16
|
+
const eventId = body?.id;
|
|
17
|
+
if (req.method !== 'POST' || !eventId) {
|
|
18
|
+
res.sendStatus(405);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
// https://developer.paypal.com/docs/integration/direct/webhooks/notification-messages/
|
|
22
|
+
const transactionCode = body && body.resource
|
|
23
|
+
&& (body.resource.sale_id || body.resource.id);
|
|
24
|
+
logger.info(`PayPal webhook ${eventId}`, {
|
|
25
|
+
transactionCode,
|
|
26
|
+
parentPayment: body.resource?.parent_payment,
|
|
27
|
+
eventType: body.event_type,
|
|
28
|
+
});
|
|
29
|
+
if (!transactionCode) {
|
|
30
|
+
res.sendStatus(400);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (!process.env.PAYPAL_CLIENT_ID || !process.env.PAYPAL_CLIENT_SECRET) {
|
|
34
|
+
const appData = await getAppData('paypal');
|
|
35
|
+
if (appData.paypal_client_id) {
|
|
36
|
+
process.env.PAYPAL_CLIENT_ID = appData.paypal_client_id;
|
|
37
|
+
}
|
|
38
|
+
if (appData.paypal_secret) {
|
|
39
|
+
process.env.PAYPAL_CLIENT_SECRET = appData.paypal_secret;
|
|
40
|
+
}
|
|
41
|
+
if (appData.paypal_sandbox) {
|
|
42
|
+
process.env.PAYPAL_ENV = 'sandbox';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const { PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET } = process.env;
|
|
46
|
+
if (!PAYPAL_CLIENT_ID || !PAYPAL_CLIENT_SECRET) {
|
|
47
|
+
res.sendStatus(403);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const paypalEvent = await readPaypalWebhookEvent(eventId);
|
|
51
|
+
const paypalEventType = paypalEvent.event_type;
|
|
52
|
+
logger.info(`PayPal event type ${paypalEventType} for ${transactionCode}`);
|
|
53
|
+
let status = 'pending';
|
|
54
|
+
switch (paypalEventType) {
|
|
55
|
+
case 'PAYMENT.AUTHORIZATION.CREATED':
|
|
56
|
+
case 'PAYMENT.PAYOUTSBATCH.PROCESSING':
|
|
57
|
+
status = 'under_analysis';
|
|
58
|
+
break;
|
|
59
|
+
case 'PAYMENT.AUTHORIZATION.VOIDED':
|
|
60
|
+
status = 'unauthorized';
|
|
61
|
+
break;
|
|
62
|
+
case 'PAYMENT.CAPTURE.COMPLETED':
|
|
63
|
+
case 'PAYMENT.SALE.COMPLETED':
|
|
64
|
+
case 'PAYMENT.PAYOUTSBATCH.SUCCESS':
|
|
65
|
+
status = 'paid';
|
|
66
|
+
break;
|
|
67
|
+
case 'PAYMENT.CAPTURE.DENIED':
|
|
68
|
+
case 'PAYMENT.SALE.DENIED':
|
|
69
|
+
case 'PAYMENT.PAYOUTSBATCH.DENIED':
|
|
70
|
+
status = 'voided';
|
|
71
|
+
break;
|
|
72
|
+
case 'PAYMENT.CAPTURE.PENDING':
|
|
73
|
+
case 'PAYMENT.SALE.PENDING':
|
|
74
|
+
status = 'pending';
|
|
75
|
+
break;
|
|
76
|
+
case 'PAYMENT.CAPTURE.REFUNDED':
|
|
77
|
+
case 'PAYMENT.CAPTURE.REVERSED':
|
|
78
|
+
case 'PAYMENT.SALE.REFUNDED':
|
|
79
|
+
case 'PAYMENT.SALE.REVERSED':
|
|
80
|
+
case 'RISK.DISPUTE.CREATED':
|
|
81
|
+
status = 'refunded';
|
|
82
|
+
break;
|
|
83
|
+
default:
|
|
84
|
+
// Ignore unknow status
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const { data: { result: [order] } } = await api.get('orders'
|
|
88
|
+
+ `?transactions.intermediator.transaction_code=${transactionCode}`
|
|
89
|
+
+ '&fields=_id,transactions'
|
|
90
|
+
+ '&limit=1');
|
|
91
|
+
if (!order) {
|
|
92
|
+
logger.warn(`Order not found for ${transactionCode}`, {
|
|
93
|
+
body: req.body,
|
|
94
|
+
paypalEvent,
|
|
95
|
+
});
|
|
96
|
+
res.sendStatus(204);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const flags = paypalEventType.split('.');
|
|
100
|
+
const transaction = order.transactions?.find(({ intermediator }) => {
|
|
101
|
+
return intermediator?.transaction_code === String(transactionCode);
|
|
102
|
+
});
|
|
103
|
+
if (transaction?._id) {
|
|
104
|
+
await api.post(`orders/${order._id}/payments_history`, {
|
|
105
|
+
date_time: new Date().toISOString(),
|
|
106
|
+
status,
|
|
107
|
+
transaction_id: transaction._id,
|
|
108
|
+
flags: ['paypal', ...flags],
|
|
109
|
+
});
|
|
110
|
+
logger.info(`Updated ${order._id} to ${status}`);
|
|
111
|
+
res.sendStatus(201);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
res.sendStatus(200);
|
|
115
|
+
}),
|
|
116
|
+
};
|
|
117
|
+
// # sourceMappingURL=paypal-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paypal-events.js","sourceRoot":"","sources":["../src/paypal-events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AppModuleBody, ListPaymentsResponse } from '@cloudcommerce/types';
|
|
2
|
+
export declare const paypalListPayments: (modBody: AppModuleBody<"list_payments">) => Promise<ListPaymentsResponse | {
|
|
3
|
+
error: string;
|
|
4
|
+
message: string;
|
|
5
|
+
status?: undefined;
|
|
6
|
+
} | {
|
|
7
|
+
status: number;
|
|
8
|
+
error: string;
|
|
9
|
+
message: any;
|
|
10
|
+
}>;
|
|
11
|
+
export default paypalListPayments;
|