Skip to content

Commit ad45dfa

Browse files
committed
feat(stripe): implement PaymentIntent API with v2 controller
Migrate Stripe from legacy Charges API to PaymentIntent API and implement the PaymentController v2 interface. - StripeSettings extends PaymentController abstract contracts - PaymentIntent creation with shared _build_intent_params helper - Server-side amount/currency validation against reference documents - Webhook handler for payment_intent.succeeded/failed/canceled - Stripe checkout page with Card Element and confirmCardPayment - Security: reference metadata verification in confirm_payment - New fields: webhook_endpoint_url, webhook_secret, collect_billing_address - 79 tests (58 unit + 21 integration) Also: add missing create_request_log call on PayPal credential failure
1 parent cd87401 commit ad45dfa

8 files changed

Lines changed: 2291 additions & 473 deletions

File tree

payments/payment_gateways/doctype/paypal_settings/paypal_settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ def execute_set_express_checkout(self, **kwargs):
212212
response = make_post_request(url, data=params.encode("utf-8"))
213213

214214
if response.get("ACK")[0] != "Success":
215+
create_request_log(response, service_name="PayPal", status="Failed")
215216
frappe.throw(_("Looks like something is wrong with this site's Paypal configuration."))
216217

217218
return response

payments/payment_gateways/doctype/stripe_settings/stripe_settings.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,13 @@
22
// For license information, please see license.txt
33

44
frappe.ui.form.on("Stripe Settings", {
5-
refresh: function (frm) {},
5+
refresh: function (frm) {
6+
// Display the webhook endpoint URL from onload data
7+
if (frm.doc.__onload && frm.doc.__onload.webhook_endpoint_url) {
8+
frm.set_value(
9+
"webhook_endpoint_url",
10+
frm.doc.__onload.webhook_endpoint_url
11+
);
12+
}
13+
},
614
});

payments/payment_gateways/doctype/stripe_settings/stripe_settings.json

Lines changed: 51 additions & 247 deletions
Original file line numberDiff line numberDiff line change
@@ -4,312 +4,116 @@
44
"allow_import": 0,
55
"allow_rename": 0,
66
"autoname": "field:gateway_name",
7-
"beta": 0,
87
"creation": "2017-03-09 17:18:29.458397",
9-
"custom": 0,
10-
"docstatus": 0,
118
"doctype": "DocType",
12-
"document_type": "",
139
"editable_grid": 1,
1410
"engine": "InnoDB",
1511
"fields": [
1612
{
17-
"allow_bulk_edit": 0,
18-
"allow_in_quick_entry": 0,
19-
"allow_on_submit": 0,
20-
"bold": 0,
21-
"collapsible": 0,
22-
"columns": 0,
2313
"fieldname": "gateway_name",
2414
"fieldtype": "Data",
25-
"hidden": 0,
26-
"ignore_user_permissions": 0,
27-
"ignore_xss_filter": 0,
28-
"in_filter": 0,
29-
"in_global_search": 0,
3015
"in_list_view": 1,
31-
"in_standard_filter": 0,
3216
"label": "Payment Gateway Name",
33-
"length": 0,
34-
"no_copy": 0,
35-
"permlevel": 0,
36-
"precision": "",
37-
"print_hide": 0,
38-
"print_hide_if_no_value": 0,
39-
"read_only": 0,
40-
"remember_last_selected_value": 0,
41-
"report_hide": 0,
4217
"reqd": 1,
43-
"search_index": 0,
44-
"set_only_once": 0,
45-
"translatable": 0,
46-
"unique": 0
18+
"unique": 1
4719
},
4820
{
49-
"allow_bulk_edit": 0,
50-
"allow_in_quick_entry": 0,
51-
"allow_on_submit": 0,
52-
"bold": 0,
53-
"collapsible": 0,
54-
"columns": 0,
5521
"fieldname": "publishable_key",
5622
"fieldtype": "Data",
57-
"hidden": 0,
58-
"ignore_user_permissions": 0,
59-
"ignore_xss_filter": 0,
60-
"in_filter": 0,
61-
"in_global_search": 0,
6223
"in_list_view": 1,
63-
"in_standard_filter": 0,
6424
"label": "Publishable Key",
65-
"length": 0,
66-
"no_copy": 0,
67-
"permlevel": 0,
68-
"precision": "",
69-
"print_hide": 0,
70-
"print_hide_if_no_value": 0,
71-
"read_only": 0,
72-
"remember_last_selected_value": 0,
73-
"report_hide": 0,
74-
"reqd": 1,
75-
"search_index": 0,
76-
"set_only_once": 0,
77-
"translatable": 0,
78-
"unique": 0
25+
"reqd": 1
7926
},
8027
{
81-
"allow_bulk_edit": 0,
82-
"allow_in_quick_entry": 0,
83-
"allow_on_submit": 0,
84-
"bold": 0,
85-
"collapsible": 0,
86-
"columns": 0,
8728
"fieldname": "column_break_3",
88-
"fieldtype": "Column Break",
89-
"hidden": 0,
90-
"ignore_user_permissions": 0,
91-
"ignore_xss_filter": 0,
92-
"in_filter": 0,
93-
"in_global_search": 0,
94-
"in_list_view": 0,
95-
"in_standard_filter": 0,
96-
"length": 0,
97-
"no_copy": 0,
98-
"permlevel": 0,
99-
"precision": "",
100-
"print_hide": 0,
101-
"print_hide_if_no_value": 0,
102-
"read_only": 0,
103-
"remember_last_selected_value": 0,
104-
"report_hide": 0,
105-
"reqd": 0,
106-
"search_index": 0,
107-
"set_only_once": 0,
108-
"translatable": 0,
109-
"unique": 0
29+
"fieldtype": "Column Break"
11030
},
11131
{
112-
"allow_bulk_edit": 0,
113-
"allow_in_quick_entry": 0,
114-
"allow_on_submit": 0,
115-
"bold": 0,
116-
"collapsible": 0,
117-
"columns": 0,
11832
"fieldname": "secret_key",
11933
"fieldtype": "Password",
120-
"hidden": 0,
121-
"ignore_user_permissions": 0,
122-
"ignore_xss_filter": 0,
123-
"in_filter": 0,
124-
"in_global_search": 0,
12534
"in_list_view": 1,
126-
"in_standard_filter": 0,
12735
"label": "Secret Key",
128-
"length": 0,
129-
"no_copy": 0,
130-
"permlevel": 0,
131-
"precision": "",
132-
"print_hide": 0,
133-
"print_hide_if_no_value": 0,
134-
"read_only": 0,
135-
"remember_last_selected_value": 0,
136-
"report_hide": 0,
137-
"reqd": 1,
138-
"search_index": 0,
139-
"set_only_once": 0,
140-
"translatable": 0,
141-
"unique": 0
36+
"reqd": 1
37+
},
38+
{
39+
"fieldname": "webhook_section",
40+
"fieldtype": "Section Break",
41+
"label": "Webhook Configuration"
42+
},
43+
{
44+
"description": "Copy this URL to your Stripe Dashboard → Developers → Webhooks → Add endpoint",
45+
"fieldname": "webhook_endpoint_url",
46+
"fieldtype": "Data",
47+
"label": "Webhook Endpoint URL",
48+
"read_only": 1
49+
},
50+
{
51+
"description": "Get this from your Stripe Dashboard → Developers → Webhooks → Signing secret",
52+
"fieldname": "webhook_secret",
53+
"fieldtype": "Password",
54+
"label": "Webhook Signing Secret"
55+
},
56+
{
57+
"fieldname": "column_break_webhook",
58+
"fieldtype": "Column Break"
59+
},
60+
{
61+
"default": "0",
62+
"description": "Enable to see detailed logs in Error Log",
63+
"fieldname": "enable_debug_logging",
64+
"fieldtype": "Check",
65+
"label": "Enable Debug Logging"
14266
},
14367
{
144-
"allow_bulk_edit": 0,
145-
"allow_in_quick_entry": 0,
146-
"allow_on_submit": 0,
147-
"bold": 0,
148-
"collapsible": 0,
149-
"columns": 0,
15068
"fieldname": "section_break_5",
15169
"fieldtype": "Section Break",
152-
"hidden": 0,
153-
"ignore_user_permissions": 0,
154-
"ignore_xss_filter": 0,
155-
"in_filter": 0,
156-
"in_global_search": 0,
157-
"in_list_view": 0,
158-
"in_standard_filter": 0,
159-
"length": 0,
160-
"no_copy": 0,
161-
"permlevel": 0,
162-
"precision": "",
163-
"print_hide": 0,
164-
"print_hide_if_no_value": 0,
165-
"read_only": 0,
166-
"remember_last_selected_value": 0,
167-
"report_hide": 0,
168-
"reqd": 0,
169-
"search_index": 0,
170-
"set_only_once": 0,
171-
"translatable": 0,
172-
"unique": 0
70+
"label": "Appearance"
17371
},
17472
{
175-
"allow_bulk_edit": 0,
176-
"allow_in_quick_entry": 0,
177-
"allow_on_submit": 0,
178-
"bold": 0,
179-
"collapsible": 0,
180-
"columns": 0,
18173
"fieldname": "header_img",
18274
"fieldtype": "Attach Image",
183-
"hidden": 0,
184-
"ignore_user_permissions": 0,
185-
"ignore_xss_filter": 0,
186-
"in_filter": 0,
187-
"in_global_search": 0,
188-
"in_list_view": 0,
189-
"in_standard_filter": 0,
190-
"label": "Header Image",
191-
"length": 0,
192-
"no_copy": 0,
193-
"permlevel": 0,
194-
"precision": "",
195-
"print_hide": 0,
196-
"print_hide_if_no_value": 0,
197-
"read_only": 0,
198-
"remember_last_selected_value": 0,
199-
"report_hide": 0,
200-
"reqd": 0,
201-
"search_index": 0,
202-
"set_only_once": 0,
203-
"translatable": 0,
204-
"unique": 0
75+
"label": "Header Image"
20576
},
20677
{
207-
"allow_bulk_edit": 0,
208-
"allow_in_quick_entry": 0,
209-
"allow_on_submit": 0,
210-
"bold": 0,
211-
"collapsible": 0,
212-
"columns": 0,
21378
"fieldname": "column_break_7",
214-
"fieldtype": "Column Break",
215-
"hidden": 0,
216-
"ignore_user_permissions": 0,
217-
"ignore_xss_filter": 0,
218-
"in_filter": 0,
219-
"in_global_search": 0,
220-
"in_list_view": 0,
221-
"in_standard_filter": 0,
222-
"length": 0,
223-
"no_copy": 0,
224-
"permlevel": 0,
225-
"precision": "",
226-
"print_hide": 0,
227-
"print_hide_if_no_value": 0,
228-
"read_only": 0,
229-
"remember_last_selected_value": 0,
230-
"report_hide": 0,
231-
"reqd": 0,
232-
"search_index": 0,
233-
"set_only_once": 0,
234-
"translatable": 0,
235-
"unique": 0
79+
"fieldtype": "Column Break"
23680
},
23781
{
238-
"allow_bulk_edit": 0,
239-
"allow_in_quick_entry": 0,
240-
"allow_on_submit": 0,
241-
"bold": 0,
242-
"collapsible": 0,
243-
"columns": 0,
82+
"description": "URL to redirect after successful payment (optional)",
24483
"fieldname": "redirect_url",
24584
"fieldtype": "Data",
246-
"hidden": 0,
247-
"ignore_user_permissions": 0,
248-
"ignore_xss_filter": 0,
249-
"in_filter": 0,
250-
"in_global_search": 0,
251-
"in_list_view": 0,
252-
"in_standard_filter": 0,
253-
"label": "Redirect URL",
254-
"length": 0,
255-
"no_copy": 0,
256-
"permlevel": 0,
257-
"precision": "",
258-
"print_hide": 0,
259-
"print_hide_if_no_value": 0,
260-
"read_only": 0,
261-
"remember_last_selected_value": 0,
262-
"report_hide": 0,
263-
"reqd": 0,
264-
"search_index": 0,
265-
"set_only_once": 0,
266-
"translatable": 0,
267-
"unique": 0
85+
"label": "Success Redirect URL"
86+
},
87+
{
88+
"default": "0",
89+
"description": "Collect customer billing address on checkout (required for some regions like India)",
90+
"fieldname": "collect_billing_address",
91+
"fieldtype": "Check",
92+
"label": "Collect Billing Address"
26893
}
26994
],
270-
"has_web_view": 0,
271-
"hide_heading": 0,
272-
"hide_toolbar": 0,
273-
"idx": 0,
274-
"image_view": 0,
275-
"in_create": 0,
276-
"is_submittable": 0,
277-
"issingle": 0,
278-
"istable": 0,
279-
"max_attachments": 0,
280-
"modified": "2022-07-24 13:32:14.429916",
95+
"index_web_pages_for_search": 1,
96+
"links": [],
97+
"modified": "2026-01-11 21:00:00.000000",
28198
"modified_by": "Administrator",
28299
"module": "Payment Gateways",
283100
"name": "Stripe Settings",
284-
"name_case": "",
285101
"owner": "Administrator",
286102
"permissions": [
287103
{
288-
"amend": 0,
289-
"cancel": 0,
290104
"create": 1,
291105
"delete": 1,
292106
"email": 1,
293-
"export": 0,
294-
"if_owner": 0,
295-
"import": 0,
296-
"permlevel": 0,
297107
"print": 1,
298108
"read": 1,
299-
"report": 0,
300109
"role": "System Manager",
301-
"set_user_permissions": 0,
302110
"share": 1,
303-
"submit": 0,
304111
"write": 1
305112
}
306113
],
307114
"quick_entry": 1,
308-
"read_only": 0,
309-
"read_only_onload": 0,
310-
"show_name_in_global_search": 0,
311115
"sort_field": "modified",
312116
"sort_order": "DESC",
313-
"track_changes": 0,
314-
"track_seen": 0
315-
}
117+
"states": [],
118+
"track_changes": 1
119+
}

0 commit comments

Comments
 (0)