PageSourceSearch

https://www.prairiequilt.com/1759150467/js/components/stripe-payment-request/PaymentRequestModel.js

js prairiequilt.com collected 2026-09-25 20:59:25 UTC 17,738 bytes, 452 lines download raw bytes

1var PaymentRequestModel = function (context) {
2    /**
3     * Private property is one of contexts
4     * @type {CheckoutContextWrapper}
5     * @private
6     */
7    var _context = context;
8
9    /**
10     * Saving a payment modal state between opens
11     * Google Pay needs it because paymentRequest doesn't call 'shippingaddresschange' and 'shippingoptionchange'
12     * if nothing has changes (for ex. if modal was closed with default address and option)
13     * @type {{total: {amount: number}, isShown: boolean, shippingAddress: {country: string, city: string, postalCode: string, recipient: string, region: string, addressLine: string[]}, shippingOptionId: ?string, shippingOptions: object[]}}
14     * @private
15     */
16    var _state = {
17        isShown: false,
18        shippingOptionId: null,
19        shippingOptions: [],
20        shippingAddress: {
21            recipient: '',
22            country: '',
23            city: '',
24            region: '',
25            postalCode: '',
26            addressLine: [],
27        },
28        total: {
29            amount: 0,
30        },
31    };
32
33    /**
34     * @param shippingOptions {{id: string, label: string, detail: string, amount: number}[]}
35     * @returns {{id: string, label: string, detail: string, amount: number}[]}
36     */
37    var appendRandStringToShippingOptionId = function (shippingOptions) {
38        var rand = (Math.random() + 1).toString(36).substring(3, 13);
39
40        return shippingOptions.map(function (option) {
41            return Object.assign({}, option, {
42                id: rand + ':' + option.id,
43            });
44        });
45    };
46
47    /**
48     * @param id {string}
49     * @returns {string|null}
50     */
51    var getShippingOptionIdFromStringWithRand = function (id) {
52        var matches = id.match(/^([\w]{5,10}):([\d]+)$/);
53
54        return matches ? matches[2] : null;
55    };
56
57    /**
58     * @param token {string}
59     * @param data {{payment_method: string}}
60     * @param options {{handleActions: boolean}?}
61     * @returns {Promise<Object>}
62     */
63    var _makePayment = function (token, data, options) {
64        return _context.getStripe().confirmCardPayment(token, data, options)
65    };
66
67    /**
68     * @param token {string}
69     * @param paymentMethod {string}
70     * @returns {Promise<Object>}
71     */
72    var _processPayment = function (token, paymentMethod) {
73        return _makePayment(token, {payment_method: paymentMethod}, {handleActions: false})
74            .then(function (result) {
75                if (result.error || result.paymentIntent.status !== 'requires_action') {
76                    return result;
77                }
78
79                return _makePayment(token, {payment_method: paymentMethod});
80            })
81            .then(function (result) {
82                if (result.error) {
83                    throw new Error('Unable to process payment');
84                }
85
86                return result;
87            });
88    };
89
90    /**
91     * @param result {Object}
92     * @returns {Object}
93     */
94    var _handlePaymentResult = function (result) {
95        console.info('Payment is succeed', result);
96
97        return result;
98    };
99
100    /**
101     * @param paymentMethod {string}
102     * @returns {Promise}
103     */
104    var _handlePaymentRequest = function (paymentMethod) {
105        return _context.createTransaction()
106            .then(function () {
107                return _context.createPaymentIntent(paymentMethod);
108            })
109            .then(function (token) {
110                return _processPayment(token, paymentMethod);
111            })
112            .then(function (result) {
113                return _handlePaymentResult(result);
114            })
115            .then(function (result) {
116                return _context.handleIntentResult(result);
117            })
118            .then(function () {
119                return _context.finishTransaction();
120            });
121    };
122
123    /**
124     * @returns {Promise<Object>}
125     */
126    var _createPaymentRequest = function () {
127        var shippingAddress = _context.getShippingAddress();
128
129        _state.shippingAddress.country = shippingAddress.country;
130        _state.shippingAddress.region = shippingAddress.region;
131        _state.shippingAddress.city = shippingAddress.city;
132        _state.shippingAddress.postalCode = shippingAddress.postalCode;
133        _state.shippingAddress.addressLine = shippingAddress.addressLine;
134        _state.shippingAddress.recipient = shippingAddress.recipient;
135
136        if (_context.areShippingOptionsRequired()) {
137            _state.shippingOptions = _context.getRainRequestPaymentShippingOptions();
138            console.info('creating', 'shippingOptions', _state.shippingOptions);
139
140            _state.shippingOptionId = _state.shippingOptions.length ? _state.shippingOptions[0].id : null;
141            console.info('creating', 'shippingOptionId', _state.shippingOptionId);
142        }
143
144        var totalAmountPromise = new Promise(function (resolve) {
145            if (!_state.shippingOptionId) {
146                return resolve(_context.getTotalAmount());
147            }
148
149            // Calculate total amount with the first shipping option and rollback changes
150            var shippingOptionId = _context.getShippingOptionId();
151
152            _context.setShippingOptionId(_state.shippingOptionId);
153            _context.onShippingOptionChange(false).then(function () {
154                var totalAmount = _context.getTotalAmount();
155
156                _context.setShippingOptionId(shippingOptionId);
157                _context.onShippingOptionChange(false).then(function () {
158                    return resolve(totalAmount);
159                });
160            });
161        });
162
163        return totalAmountPromise.then(function (totalAmount) {
164            _state.total.amount = totalAmount;
165
166            console.info('creating', 'total.amount', _state.total.amount);
167        }).then(function () {
168            var paymentRequestOptions = {
169                country: _context.getCountry(),
170                currency: _context.getCurrency(),
171                total: {
172                    label: 'Order',
173                    amount: _state.total.amount,
174                },
175                requestPayerName: true,
176                requestPayerEmail: true,
177                requestPayerPhone: true,
178                requestShipping: false,
179                disableWallets: ['browserCard'],
180            };
181
182            if (_state.shippingOptions.length) {
183                paymentRequestOptions.requestShipping = true;
184                paymentRequestOptions.shippingOptions = appendRandStringToShippingOptionId(_state.shippingOptions);
185            }
186
187            return paymentRequestOptions;
188        }).then(function (paymentRequestOptions) {
189            var paymentRequest = _context.getStripe().paymentRequest(paymentRequestOptions);
190
191            paymentRequest.on('shippingoptionchange', function (event) {
192                console.info('event:shippingoptionchange', event);
193
194                _state.shippingOptionId = event.shippingOption ? getShippingOptionIdFromStringWithRand(event.shippingOption.id) : null;
195
196                console.info('event:shippingoptionchange', 'shippingOptionId', _state.shippingOptionId);
197                console.info('event:shippingoptionchange', 'shippingOptionId', 'update checkout', _state.shippingOptionId);
198
199                _context.setShippingOptionId(_state.shippingOptionId);
200                _context.onShippingOptionChange(false)
201                    .catch(function (error) {
202                        event.updateWith({status: 'invalid_shipping_address'});
203
204                        return Promise.reject(error);
205                    }).then(function () {
206                    _state.total.amount = _context.getTotalAmount();
207
208                    console.info('event:shippingoptionchange', 'total.amount', _state.total.amount);
209
210                    event.updateWith({
211                        status: 'success',
212                        total: {
213                            label: 'Order',
214                            amount: _state.total.amount,
215                        },
216                    });
217                });
218            });
219
220            paymentRequest.on('shippingaddresschange', function (event) {
221                console.info('event:shippingaddresschange', event);
222
223                var shippingAddress = event.shippingAddress;
224
225                _state.shippingAddress.country = shippingAddress.country;
226                _state.shippingAddress.region = shippingAddress.region;
227                _state.shippingAddress.city = shippingAddress.city;
228                _state.shippingAddress.postalCode = shippingAddress.postalCode;
229                _state.shippingAddress.addressLine = shippingAddress.addressLine;
230                _state.shippingAddress.recipient = shippingAddress.recipient;
231
232                _context.setShippingAddress(shippingAddress);
233
234                _context.loadShippingOptions(false)
235                    .then(function () {
236                        var shippingOptions = _context.getRainRequestPaymentShippingOptions();
237                        console.info('event:shippingaddresschange', 'shippingOptions', shippingOptions);
238
239                        _state.shippingOptions = shippingOptions;
240                        _state.shippingOptionId = shippingOptions.length ? shippingOptions[0].id : null;
241
242                        console.info('event:shippingaddresschange', 'shippingOptionId', 'first from shippingOptions', _state.shippingOptionId);
243                        console.info('event:shippingaddresschange', 'shippingOptionId', 'update checkout', _state.shippingOptionId);
244
245                        _context.setShippingOptionId(_state.shippingOptionId);
246
247                        return _context.onShippingOptionChange(false).then(function () {
248                            return {shippingOptions: appendRandStringToShippingOptionId(shippingOptions)};
249                        });
250                    })
251                    .then(function (data) {
252                        _state.total.amount = _context.getTotalAmount();
253
254                        console.info('event:shippingaddresschange', 'total.amount', _state.total.amount);
255
256                        return Object.assign(data, {
257                            total: {
258                                label: 'Order',
259                                amount: _state.total.amount,
260                            },
261                        });
262                    })
263                    .then(function (data) {
264                        event.updateWith(Object.assign({status: 'success'}, data));
265                    })
266                    .catch(function (e) {
267                        console.error(e);
268
269                        event.updateWith({status: 'invalid_shipping_address'});
270                    });
271            });
272
273            paymentRequest.on('paymentmethod', function (event) {
274                console.info('event:paymentmethod', event);
275
276                try {
277                    var billing = event.paymentMethod.billing_details;
278
279                    _context.setBillingInfo(billing.name, billing.email, billing.phone, billing.address);
280                    _context.onBillingChange(true);
281                } catch (error) {
282                    event.complete('fail');
283
284                    throw error;
285                }
286
287                try {
288                    var shipping = event.shippingAddress;
289
290                    _context.setShippingAddress(shipping);
291                } catch (error) {
292                    event.complete('invalid_shipping_address');
293
294                    throw error;
295                }
296
297                _state.shippingOptionId = event.shippingOption ? getShippingOptionIdFromStringWithRand(event.shippingOption.id) : null;
298
299                if (_context.getShippingOptionId() !== _state.shippingOptionId) {
300                    console.warn('event:paymentmethod', 'shippingOptionId', 'checkout value', _context.getShippingOptionId(), '!==', 'modal value', _state.shippingOptionId);
301                }
302
303                _context.loadShippingOptions(true)
304                    .then(function () {
305                        _context.setShippingOptionId(_state.shippingOptionId);
306
307                        return _context.onShippingOptionChange(true);
308                    })
309                    .then(function () {
310                        return _handlePaymentRequest(event.paymentMethod.id);
311                    })
312                    .then(function () {
313                        event.complete('success');
314                    })
315                    .catch(function (e) {
316                        event.complete('fail');
317
318                        throw e;
319                    });
320            });
321
322            paymentRequest.on('cancel', function () {
323                console.info('event:cancel', 'reset', 'billingAddress');
324
325                _context.resetBillingAddress();
326                _context.onBillingChange(false);
327
328                console.info('event:cancel', 'reset', 'shippingOptionId');
329
330                _context.setShippingOptionId(null);
331
332                _context.onShippingOptionChange(false).then(function () {
333                    console.info('event:cancel', 'reset', 'shippingAddress');
334
335                    _context.resetShippingAddress();
336                }).then(function () {
337                    console.info('event:cancel', 'reset', 'shippingOptions');
338
339                    return _context.loadShippingOptions(false);
340                }).then(function () {
341                    console.info('event:cancel', 'reset', 'finished');
342
343                    _state.isShown = false;
344                });
345            });
346
347            return paymentRequest;
348        });
349    };
350
351    /**
352     * @param paymentRequest {Object}
353     * @returns {Object}
354     */
355    var _createPaymentRequestButton = function (paymentRequest) {
356        var paymentRequestButton = _context.getStripe().elements().create('paymentRequestButton', {
357            paymentRequest: paymentRequest,
358        });
359
360        paymentRequestButton.on('click', function () {
361            console.info('event:click', 'total.amount', _context.getTotalAmount());
362
363            var data = {
364                total: {
365                    label: 'Order',
366                    amount: _context.getTotalAmount(),
367                },
368            };
369
370            if (_context.areShippingOptionsRequired()) {
371                console.info('event:click', 'shippingOptions', _state.shippingOptions);
372                data.shippingOptions = _state.shippingOptions;
373                _state.shippingOptionId = data.shippingOptions.length ? data.shippingOptions[0].id : null;
374                console.info('event:click', 'shippingOptionId', 'first from shippingOptions', _state.shippingOptionId);
375            }
376
377            paymentRequest.update(data);
378
379            _state.isShown = true;
380
381            _context.setShippingAddress(_state.shippingAddress);
382            _context.loadShippingOptions(false).then(function () {
383                var shippingOptions = _context.getRainRequestPaymentShippingOptions();
384                var shippingOptionId = shippingOptions.length ? shippingOptions[0].id : null;
385
386                console.info('event:click', 'shippingOptions', 'from checkout', shippingOptions);
387                console.info('event:click', 'shippingOptionId', 'first from shippingOptions', 'update checkout', shippingOptionId);
388
389                _context.setShippingOptionId(shippingOptionId);
390
391                return _context.onShippingOptionChange(false).then(function () {
392                    if (shippingOptionId !== _state.shippingOptionId) {
393                        console.warn('event:click', 'shippingOptionId', 'checkout value', shippingOptionId, '!==', 'modal value', _state.shippingOptionId);
394                    }
395
396                    var totalAmount = _context.getTotalAmount();
397
398                    if (totalAmount !== _state.total.amount) {
399                        console.warn('event:click', 'total.amount', 'checkout value', totalAmount, '!==', 'modal value', _state.total.amount);
400                    }
401
402                    var shippingOptionIds = shippingOptions.map(function (shippingOption) {
403                        return shippingOption.id;
404                    });
405
406                    var isShippingOptionsSame =
407                        shippingOptions.length === _state.shippingOptions.length
408                        && _state.shippingOptions.every(function (shippingOption) {
409                            return shippingOptionIds.some(function (shippingOptionId) {
410                                return shippingOption.id === shippingOptionId;
411                            });
412                        });
413
414                    if (!isShippingOptionsSame) {
415                        console.warn('event:click', 'shippingOptions', 'checkout value', shippingOptions, '!==', 'modal value', _state.shippingOptions);
416                    }
417                });
418            });
419        });
420
421        return paymentRequestButton;
422    };
423
424    /**
425     * @returns {Promise<void>}
426     * @private
427     */
428    var _initPaymentRequestBtn = function () {
429        return _createPaymentRequest().then(function (paymentRequest) {
430            var paymentRequestButton = _createPaymentRequestButton(paymentRequest);
431
432            return paymentRequest.canMakePayment().then(function (result) {
433                if (result) {
434                    _context.showPaymentRequestButton();
435
436                    paymentRequestButton.mount('#' + _context.getPaymentRequestButtonId());
437                }
438            });
439        });
440    };
441
442    /**
443     * @returns {Promise<void>}
444     */
445    this.init = function () {
446        if (!_context.isEnabled()) {
447            return Promise.resolve();
448        }
449
450        return _initPaymentRequestBtn();
451    };
452};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.