[{"data":1,"prerenderedAt":2044},["ShallowReactive",2],{"navigation_docs":3,"-modules-payments":153,"-modules-payments-surround":2039},[4,35,50,59,144],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting started",false,"\u002Fgetting-started","1.getting-started",[10,15,20,25,30],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F2.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Local Development","\u002Fgetting-started\u002Flocal-development","1.getting-started\u002F3.local-development","i-lucide-terminal",{"title":21,"path":22,"stem":23,"icon":24},"Publishing Packages","\u002Fgetting-started\u002Fpublishing","1.getting-started\u002F4.publishing","i-lucide-package-check",{"title":26,"path":27,"stem":28,"icon":29},"Writing a Module","\u002Fgetting-started\u002Fwriting-a-module","1.getting-started\u002F5.writing-a-module","i-lucide-puzzle",{"title":31,"path":32,"stem":33,"icon":34},"UX Patterns","\u002Fgetting-started\u002Fux-patterns","1.getting-started\u002F6.ux-patterns","i-lucide-layout-template",{"title":36,"path":37,"stem":38,"children":39},"Applications","\u002Fapplications","2.applications",[40,45],{"title":41,"path":42,"stem":43,"icon":44},"Website","\u002Fapplications\u002Fwebsite","2.applications\u002F1.website","i-lucide-layout-dashboard",{"title":46,"path":47,"stem":48,"icon":49},"Docs","\u002Fapplications\u002Fdocs","2.applications\u002F2.docs","i-lucide-book-open",{"title":51,"path":52,"stem":53,"children":54},"Layers","\u002Flayers","3.layers",[55],{"title":56,"path":57,"stem":58},"Base Layer","\u002Flayers\u002Fbase","3.layers\u002F1.base",{"title":60,"path":61,"stem":62,"children":63},"Modules","\u002Fmodules","4.modules",[64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140],{"title":65,"path":66,"stem":67},"Account","\u002Fmodules\u002Faccount","4.modules\u002F01.account",{"title":69,"path":70,"stem":71},"Admin","\u002Fmodules\u002Fadmin","4.modules\u002F02.admin",{"title":73,"path":74,"stem":75},"Auth","\u002Fmodules\u002Fauth","4.modules\u002F03.auth",{"title":77,"path":78,"stem":79},"Authorization","\u002Fmodules\u002Fauthorization","4.modules\u002F04.authorization",{"title":81,"path":82,"stem":83},"Cookie Consent","\u002Fmodules\u002Fcookie-consent","4.modules\u002F05.cookie-consent",{"title":85,"path":86,"stem":87},"Events","\u002Fmodules\u002Fevents","4.modules\u002F06.events",{"title":89,"path":90,"stem":91},"Forms","\u002Fmodules\u002Fforms","4.modules\u002F07.forms",{"title":93,"path":94,"stem":95},"MCP","\u002Fmodules\u002Fmcp","4.modules\u002F08.mcp",{"title":97,"path":98,"stem":99},"Menu","\u002Fmodules\u002Fmenu","4.modules\u002F09.menu",{"title":101,"path":102,"stem":103},"Module Kit","\u002Fmodules\u002Fmodule-kit","4.modules\u002F10.module-kit",{"title":105,"path":106,"stem":107},"Notify","\u002Fmodules\u002Fnotify","4.modules\u002F11.notify",{"title":109,"path":110,"stem":111},"OAuth Server","\u002Fmodules\u002Foauth-server","4.modules\u002F12.oauth-server",{"title":113,"path":114,"stem":115},"Payments","\u002Fmodules\u002Fpayments","4.modules\u002F13.payments",{"title":117,"path":118,"stem":119},"Preferences","\u002Fmodules\u002Fpreferences","4.modules\u002F14.preferences",{"title":121,"path":122,"stem":123},"Stripe","\u002Fmodules\u002Fstripe","4.modules\u002F15.stripe",{"title":125,"path":126,"stem":127},"Subscriptions","\u002Fmodules\u002Fsubscriptions","4.modules\u002F16.subscriptions",{"title":129,"path":130,"stem":131},"UI","\u002Fmodules\u002Fui","4.modules\u002F17.ui",{"title":133,"path":134,"stem":135},"Users","\u002Fmodules\u002Fusers","4.modules\u002F18.users",{"title":137,"path":138,"stem":139},"Widget","\u002Fmodules\u002Fwidget","4.modules\u002F19.widget",{"title":141,"path":142,"stem":143},"Email Templates","\u002Fmodules\u002Femail-templates","4.modules\u002F20.email-templates",{"title":145,"path":146,"stem":147,"children":148},"Packages","\u002Fpackages","5.packages",[149],{"title":150,"path":151,"stem":152},"CLI","\u002Fpackages\u002Fcli","5.packages\u002F4.cli",{"id":154,"title":113,"body":155,"description":2033,"extension":2034,"links":2035,"meta":2036,"navigation":660,"path":114,"seo":2037,"stem":115,"__hash__":2038},"docs\u002F4.modules\u002F13.payments.md",{"type":156,"value":157,"toc":2021},"minimark",[158,169,227,272,277,404,408,481,485,488,575,585,1082,1085,1152,1156,1163,1266,1374,1383,1387,1480,1492,1496,1531,1558,1612,1616,1623,1828,1834,1838,1880,1886,1889,1918,1922,1962,2017],[159,160,161,162,165,166,168],"p",{},"One-time payments on top of ",[163,164,121],"a",{"href":122},". The module is event-agnostic: other modules (for example\n",[163,167,85],{"href":86},") ask it to charge something and are told through hooks when the money arrives.",[170,171,172,207,217],"ul",{},[173,174,175,179,180,187,188,191,192,195,196,195,199,202,203,206],"li",{},[176,177,178],"strong",{},"Stripe events are the only inbound signal."," The module has no webhook route of its own. It registers a handler with\n",[163,181,183],{"href":182},"\u002Fmodules\u002Fstripe#in-a-module",[184,185,186],"code",{},"registerStripeEventHandler"," for ",[184,189,190],{},"checkout.session.completed",",\n",[184,193,194],{},"checkout.session.async_payment_succeeded",", ",[184,197,198],{},"checkout.session.async_payment_failed",[184,200,201],{},"checkout.session.expired"," and\n",[184,204,205],{},"charge.refunded",". The success redirect never marks anything as paid.",[173,208,209,212,213,216],{},[176,210,211],{},"Prices are inline."," Checkout sessions use ",[184,214,215],{},"price_data",", so no Stripe products or prices need syncing between\nenvironments.",[173,218,219,222,223,226],{},[176,220,221],{},"Hooks, not coupling."," State transitions are announced through Nitro hooks; consumers filter on\n",[184,224,225],{},"payment.referenceType",".",[228,229,230,233,234,237,238,195,241,191,246,251,252,257,258,233,261,251,266,271],"note",{},[176,231,232],{},"Requires"," ",[184,235,236],{},"@nuxthub\u002Fcore"," (KV on), ",[184,239,240],{},"@frigear-nu\u002Fmodule-kit",[163,242,243],{"href":74},[184,244,245],{},"@frigear-nu\u002Fauth",[163,247,248],{"href":134},[184,249,250],{},"@frigear-nu\u002Fusers"," and ",[163,253,254],{"href":122},[184,255,256],{},"@frigear-nu\u002Fstripe"," (configure it as described there).\n",[176,259,260],{},"Optional",[163,262,263],{"href":138},[184,264,265],{},"@frigear-nu\u002Fwidget",[163,267,268],{"href":70},[184,269,270],{},"@frigear-nu\u002Fadmin",": the admin user tab and\ncard are only added when both are present.",[273,274,276],"h2",{"id":275},"quick-setup","Quick setup",[278,279,284],"pre",{"className":280,"code":281,"language":282,"meta":283,"style":283},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n  modules: ['@frigear-nu\u002Fusers', '@frigear-nu\u002Fstripe', '@frigear-nu\u002Fpayments'],\n  payments: {\n    settings: { checkoutExpiresInMinutes: 30 },\n  },\n})\n","ts","",[184,285,286,310,355,366,389,395],{"__ignoreMap":283},[287,288,291,295,298,302,306],"span",{"class":289,"line":290},"line",1,[287,292,294],{"class":293},"s7zQu","export",[287,296,297],{"class":293}," default",[287,299,301],{"class":300},"s2Zo4"," defineNuxtConfig",[287,303,305],{"class":304},"sTEyZ","(",[287,307,309],{"class":308},"sMK4o","{\n",[287,311,313,317,320,323,326,329,331,334,337,339,341,343,345,348,350,353],{"class":289,"line":312},2,[287,314,316],{"class":315},"swJcz","  modules",[287,318,319],{"class":308},":",[287,321,322],{"class":304}," [",[287,324,325],{"class":308},"'",[287,327,250],{"class":328},"sfazB",[287,330,325],{"class":308},[287,332,333],{"class":308},",",[287,335,336],{"class":308}," '",[287,338,256],{"class":328},[287,340,325],{"class":308},[287,342,333],{"class":308},[287,344,336],{"class":308},[287,346,347],{"class":328},"@frigear-nu\u002Fpayments",[287,349,325],{"class":308},[287,351,352],{"class":304},"]",[287,354,191],{"class":308},[287,356,358,361,363],{"class":289,"line":357},3,[287,359,360],{"class":315},"  payments",[287,362,319],{"class":308},[287,364,365],{"class":308}," {\n",[287,367,369,372,374,377,380,382,386],{"class":289,"line":368},4,[287,370,371],{"class":315},"    settings",[287,373,319],{"class":308},[287,375,376],{"class":308}," {",[287,378,379],{"class":315}," checkoutExpiresInMinutes",[287,381,319],{"class":308},[287,383,385],{"class":384},"sbssI"," 30",[287,387,388],{"class":308}," },\n",[287,390,392],{"class":289,"line":391},5,[287,393,394],{"class":308},"  },\n",[287,396,398,401],{"class":289,"line":397},6,[287,399,400],{"class":308},"}",[287,402,403],{"class":304},")\n",[273,405,407],{"id":406},"options","Options",[409,410,411,430],"table",{},[412,413,414],"thead",{},[415,416,417,421,424,427],"tr",{},[418,419,420],"th",{},"Option",[418,422,423],{},"Type",[418,425,426],{},"Default",[418,428,429],{},"Purpose",[431,432,433,457],"tbody",{},[415,434,435,441,446,451],{},[436,437,438],"td",{},[184,439,440],{},"settings.checkoutExpiresInMinutes",[436,442,443],{},[184,444,445],{},"number",[436,447,448],{},[184,449,450],{},"30",[436,452,453,454,226],{},"Minutes a Checkout session stays open. Clamped to Stripe's range of 30 - 1440. Also in ",[184,455,456],{},"runtimeConfig.payments",[415,458,459,464,469,474],{},[436,460,461],{},[184,462,463],{},"settings.mcp",[436,465,466],{},[184,467,468],{},"boolean",[436,470,471],{},[184,472,473],{},"false",[436,475,476,477,480],{},"Expose the ",[184,478,479],{},"my-payments"," MCP tool.",[273,482,484],{"id":483},"server","Server",[159,486,487],{},"Auto-imported in Nitro:",[409,489,490,500],{},[412,491,492],{},[415,493,494,497],{},[418,495,496],{},"Util",[418,498,499],{},"Description",[431,501,502,523,536,549,565],{},[415,503,504,509],{},[436,505,506],{},[184,507,508],{},"createPayment(input, event?)",[436,510,511,512,515,516,519,520,226],{},"Creates the Checkout session (",[184,513,514],{},"mode: 'payment'",") and a ",[184,517,518],{},"pending"," row. Returns ",[184,521,522],{},"CreatePaymentResult",[415,524,525,530],{},[436,526,527],{},[184,528,529],{},"resumePayment(paymentId, userId, event?)",[436,531,532,533,226],{},"Returns the open session's URL, or creates a fresh session once it expired. Returns ",[184,534,535],{},"{ url }",[415,537,538,543],{},[436,539,540],{},[184,541,542],{},"refundPayment(paymentId, { amount? })",[436,544,545,546,548],{},"Asks Stripe for a (partial) refund. The status changes when ",[184,547,205],{}," arrives.",[415,550,551,559],{},[436,552,553,195,556],{},[184,554,555],{},"getPayment(id)",[184,557,558],{},"getPaymentByReference(type, id)",[436,560,561,562,226],{},"Read one payment (the latest for a reference), or ",[184,563,564],{},"null",[415,566,567,572],{},[436,568,569],{},[184,570,571],{},"listUserPayments(userId, { limit? })",[436,573,574],{},"A user's payments, newest first.",[159,576,577,580,581,584],{},[184,578,579],{},"@frigear-nu\u002Fpayments\u002Futils"," exports the types below and ",[184,582,583],{},"sumItems(items)",", which totals items in minor units.",[278,586,588],{"className":280,"code":587,"language":282,"meta":283,"style":283},"type PaymentStatus = 'pending' | 'paid' | 'failed' | 'expired' | 'refunded' | 'partially_refunded'\n\ntype PaymentItem = {\n  name: string\n  description?: string\n  amount: number      \u002F\u002F unit amount in minor units (cents \u002F øre)\n  currency: string    \u002F\u002F ISO 4217\n  quantity?: number   \u002F\u002F default 1\n}\n\ntype CreatePaymentInput = {\n  userId: number\n  items: PaymentItem[]                           \u002F\u002F one currency, total above zero\n  reference?: { type: string, id: string }       \u002F\u002F e.g. { type: 'event_ticket', id }\n  successUrl: string                             \u002F\u002F absolute URL or path on the current origin\n  cancelUrl: string\n  description?: string\n  expiresInMinutes?: number                      \u002F\u002F overrides settings.checkoutExpiresInMinutes\n  metadata?: Record\u003Cstring, string>\n}\n\ntype CreatePaymentResult = { payment: PaymentDto, url: string }\n\ntype PaymentDto = {\n  id: string                      \u002F\u002F pay_...\n  userId: number\n  status: PaymentStatus\n  amount: number\n  currency: string\n  description: string | null\n  referenceType: string | null\n  referenceId: string | null\n  refundedAmount: number\n  paidAt: string | null           \u002F\u002F ISO\n  createdAt: string               \u002F\u002F ISO\n}\n",[184,589,590,656,662,673,683,693,707,721,734,740,745,757,768,784,816,829,839,848,861,885,890,895,927,932,943,956,965,976,985,994,1008,1022,1036,1046,1064,1077],{"__ignoreMap":283},[287,591,592,596,600,603,605,607,609,612,614,617,619,621,623,626,628,630,632,635,637,639,641,644,646,648,650,653],{"class":289,"line":290},[287,593,595],{"class":594},"spNyl","type",[287,597,599],{"class":598},"sBMFI"," PaymentStatus",[287,601,602],{"class":308}," =",[287,604,336],{"class":308},[287,606,518],{"class":328},[287,608,325],{"class":308},[287,610,611],{"class":308}," |",[287,613,336],{"class":308},[287,615,616],{"class":328},"paid",[287,618,325],{"class":308},[287,620,611],{"class":308},[287,622,336],{"class":308},[287,624,625],{"class":328},"failed",[287,627,325],{"class":308},[287,629,611],{"class":308},[287,631,336],{"class":308},[287,633,634],{"class":328},"expired",[287,636,325],{"class":308},[287,638,611],{"class":308},[287,640,336],{"class":308},[287,642,643],{"class":328},"refunded",[287,645,325],{"class":308},[287,647,611],{"class":308},[287,649,336],{"class":308},[287,651,652],{"class":328},"partially_refunded",[287,654,655],{"class":308},"'\n",[287,657,658],{"class":289,"line":312},[287,659,661],{"emptyLinePlaceholder":660},true,"\n",[287,663,664,666,669,671],{"class":289,"line":357},[287,665,595],{"class":594},[287,667,668],{"class":598}," PaymentItem",[287,670,602],{"class":308},[287,672,365],{"class":308},[287,674,675,678,680],{"class":289,"line":368},[287,676,677],{"class":315},"  name",[287,679,319],{"class":308},[287,681,682],{"class":598}," string\n",[287,684,685,688,691],{"class":289,"line":391},[287,686,687],{"class":315},"  description",[287,689,690],{"class":308},"?:",[287,692,682],{"class":598},[287,694,695,698,700,703],{"class":289,"line":397},[287,696,697],{"class":315},"  amount",[287,699,319],{"class":308},[287,701,702],{"class":598}," number",[287,704,706],{"class":705},"sHwdD","      \u002F\u002F unit amount in minor units (cents \u002F øre)\n",[287,708,710,713,715,718],{"class":289,"line":709},7,[287,711,712],{"class":315},"  currency",[287,714,319],{"class":308},[287,716,717],{"class":598}," string",[287,719,720],{"class":705},"    \u002F\u002F ISO 4217\n",[287,722,724,727,729,731],{"class":289,"line":723},8,[287,725,726],{"class":315},"  quantity",[287,728,690],{"class":308},[287,730,702],{"class":598},[287,732,733],{"class":705},"   \u002F\u002F default 1\n",[287,735,737],{"class":289,"line":736},9,[287,738,739],{"class":308},"}\n",[287,741,743],{"class":289,"line":742},10,[287,744,661],{"emptyLinePlaceholder":660},[287,746,748,750,753,755],{"class":289,"line":747},11,[287,749,595],{"class":594},[287,751,752],{"class":598}," CreatePaymentInput",[287,754,602],{"class":308},[287,756,365],{"class":308},[287,758,760,763,765],{"class":289,"line":759},12,[287,761,762],{"class":315},"  userId",[287,764,319],{"class":308},[287,766,767],{"class":598}," number\n",[287,769,771,774,776,778,781],{"class":289,"line":770},13,[287,772,773],{"class":315},"  items",[287,775,319],{"class":308},[287,777,668],{"class":598},[287,779,780],{"class":304},"[]                           ",[287,782,783],{"class":705},"\u002F\u002F one currency, total above zero\n",[287,785,787,790,792,794,797,799,801,803,806,808,810,813],{"class":289,"line":786},14,[287,788,789],{"class":315},"  reference",[287,791,690],{"class":308},[287,793,376],{"class":308},[287,795,796],{"class":315}," type",[287,798,319],{"class":308},[287,800,717],{"class":598},[287,802,333],{"class":308},[287,804,805],{"class":315}," id",[287,807,319],{"class":308},[287,809,717],{"class":598},[287,811,812],{"class":308}," }",[287,814,815],{"class":705},"       \u002F\u002F e.g. { type: 'event_ticket', id }\n",[287,817,819,822,824,826],{"class":289,"line":818},15,[287,820,821],{"class":315},"  successUrl",[287,823,319],{"class":308},[287,825,717],{"class":598},[287,827,828],{"class":705},"                             \u002F\u002F absolute URL or path on the current origin\n",[287,830,832,835,837],{"class":289,"line":831},16,[287,833,834],{"class":315},"  cancelUrl",[287,836,319],{"class":308},[287,838,682],{"class":598},[287,840,842,844,846],{"class":289,"line":841},17,[287,843,687],{"class":315},[287,845,690],{"class":308},[287,847,682],{"class":598},[287,849,851,854,856,858],{"class":289,"line":850},18,[287,852,853],{"class":315},"  expiresInMinutes",[287,855,690],{"class":308},[287,857,702],{"class":598},[287,859,860],{"class":705},"                      \u002F\u002F overrides settings.checkoutExpiresInMinutes\n",[287,862,864,867,869,872,875,878,880,882],{"class":289,"line":863},19,[287,865,866],{"class":315},"  metadata",[287,868,690],{"class":308},[287,870,871],{"class":598}," Record",[287,873,874],{"class":308},"\u003C",[287,876,877],{"class":598},"string",[287,879,333],{"class":308},[287,881,717],{"class":598},[287,883,884],{"class":308},">\n",[287,886,888],{"class":289,"line":887},20,[287,889,739],{"class":308},[287,891,893],{"class":289,"line":892},21,[287,894,661],{"emptyLinePlaceholder":660},[287,896,898,900,903,905,907,910,912,915,917,920,922,924],{"class":289,"line":897},22,[287,899,595],{"class":594},[287,901,902],{"class":598}," CreatePaymentResult",[287,904,602],{"class":308},[287,906,376],{"class":308},[287,908,909],{"class":315}," payment",[287,911,319],{"class":308},[287,913,914],{"class":598}," PaymentDto",[287,916,333],{"class":308},[287,918,919],{"class":315}," url",[287,921,319],{"class":308},[287,923,717],{"class":598},[287,925,926],{"class":308}," }\n",[287,928,930],{"class":289,"line":929},23,[287,931,661],{"emptyLinePlaceholder":660},[287,933,935,937,939,941],{"class":289,"line":934},24,[287,936,595],{"class":594},[287,938,914],{"class":598},[287,940,602],{"class":308},[287,942,365],{"class":308},[287,944,946,949,951,953],{"class":289,"line":945},25,[287,947,948],{"class":315},"  id",[287,950,319],{"class":308},[287,952,717],{"class":598},[287,954,955],{"class":705},"                      \u002F\u002F pay_...\n",[287,957,959,961,963],{"class":289,"line":958},26,[287,960,762],{"class":315},[287,962,319],{"class":308},[287,964,767],{"class":598},[287,966,968,971,973],{"class":289,"line":967},27,[287,969,970],{"class":315},"  status",[287,972,319],{"class":308},[287,974,975],{"class":598}," PaymentStatus\n",[287,977,979,981,983],{"class":289,"line":978},28,[287,980,697],{"class":315},[287,982,319],{"class":308},[287,984,767],{"class":598},[287,986,988,990,992],{"class":289,"line":987},29,[287,989,712],{"class":315},[287,991,319],{"class":308},[287,993,682],{"class":598},[287,995,997,999,1001,1003,1005],{"class":289,"line":996},30,[287,998,687],{"class":315},[287,1000,319],{"class":308},[287,1002,717],{"class":598},[287,1004,611],{"class":308},[287,1006,1007],{"class":598}," null\n",[287,1009,1011,1014,1016,1018,1020],{"class":289,"line":1010},31,[287,1012,1013],{"class":315},"  referenceType",[287,1015,319],{"class":308},[287,1017,717],{"class":598},[287,1019,611],{"class":308},[287,1021,1007],{"class":598},[287,1023,1025,1028,1030,1032,1034],{"class":289,"line":1024},32,[287,1026,1027],{"class":315},"  referenceId",[287,1029,319],{"class":308},[287,1031,717],{"class":598},[287,1033,611],{"class":308},[287,1035,1007],{"class":598},[287,1037,1039,1042,1044],{"class":289,"line":1038},33,[287,1040,1041],{"class":315},"  refundedAmount",[287,1043,319],{"class":308},[287,1045,767],{"class":598},[287,1047,1049,1052,1054,1056,1058,1061],{"class":289,"line":1048},34,[287,1050,1051],{"class":315},"  paidAt",[287,1053,319],{"class":308},[287,1055,717],{"class":598},[287,1057,611],{"class":308},[287,1059,1060],{"class":598}," null",[287,1062,1063],{"class":705},"           \u002F\u002F ISO\n",[287,1065,1067,1070,1072,1074],{"class":289,"line":1066},35,[287,1068,1069],{"class":315},"  createdAt",[287,1071,319],{"class":308},[287,1073,717],{"class":598},[287,1075,1076],{"class":705},"               \u002F\u002F ISO\n",[287,1078,1080],{"class":289,"line":1079},36,[287,1081,739],{"class":308},[159,1083,1084],{},"Behaviour worth knowing:",[170,1086,1087,1107,1140],{},[173,1088,1089,251,1092,1095,1096,1099,1100,1102,1103,1106],{},[184,1090,1091],{},"successUrl",[184,1093,1094],{},"cancelUrl"," are validated (relative path or same origin) when ",[184,1097,1098],{},"event"," is passed; without ",[184,1101,1098],{}," they\nmust be absolute ",[184,1104,1105],{},"http(s)"," URLs. Invalid URLs throw 400.",[173,1108,1109,1112,1113,1116,1117,1120,1121,1124,1125,1128,1129,1132,1133,1135,1136,1139],{},[184,1110,1111],{},"resumePayment"," throws 404 for an unknown payment, and 409 when it is already paid or refunded. For an expired session\nit creates a new one from the stored ",[184,1114,1115],{},"items"," (same names, descriptions, unit amounts and quantities), runs\n",[184,1118,1119],{},"payments:checkout:before"," and the same return URL validation as ",[184,1122,1123],{},"createPayment",", and reuses the expired session's\nsuccess and cancel URLs. ",[184,1126,1127],{},"expiresInMinutes"," is not stored; the configured ",[184,1130,1131],{},"checkoutExpiresInMinutes"," applies. Payments\ncreated before ",[184,1134,1115],{}," was stored fall back to a single line item for the total, named after the description or\n",[184,1137,1138],{},"Payment","; the hook still runs.",[173,1141,1142,1145,1146,1148,1149,1151],{},[184,1143,1144],{},"refundPayment"," throws 409 unless the payment is ",[184,1147,616],{}," or ",[184,1150,652],{},", and 400 for an amount that is not\npositive or exceeds what is left to refund.",[273,1153,1155],{"id":1154},"hooks","Hooks",[159,1157,1158,1159,1162],{},"Register with ",[184,1160,1161],{},"nitro.hooks.hook(...)"," in a Nitro plugin.",[409,1164,1165,1178],{},[412,1166,1167],{},[415,1168,1169,1172,1175],{},[418,1170,1171],{},"Hook",[418,1173,1174],{},"When",[418,1176,1177],{},"Payload",[431,1179,1180,1204,1219,1233,1247],{},[415,1181,1182,1186,1199],{},[436,1183,1184],{},[184,1185,1119],{},[436,1187,1188,1189,1191,1192,1194,1195,1198],{},"Before the session is created by ",[184,1190,1123],{}," or rebuilt by ",[184,1193,1111],{},"; adjust ",[184,1196,1197],{},"ctx.params"," or throw to deny.",[436,1200,1201],{},[184,1202,1203],{},"CheckoutBeforeContext",[415,1205,1206,1211,1214],{},[436,1207,1208],{},[184,1209,1210],{},"payments:paid",[436,1212,1213],{},"Once, when the payment became paid.",[436,1215,1216],{},[184,1217,1218],{},"PaymentHookContext",[415,1220,1221,1226,1229],{},[436,1222,1223],{},[184,1224,1225],{},"payments:failed",[436,1227,1228],{},"An asynchronous payment method failed.",[436,1230,1231],{},[184,1232,1218],{},[415,1234,1235,1240,1243],{},[436,1236,1237],{},[184,1238,1239],{},"payments:expired",[436,1241,1242],{},"The Checkout session expired unpaid.",[436,1244,1245],{},[184,1246,1218],{},[415,1248,1249,1254,1262],{},[436,1250,1251],{},[184,1252,1253],{},"payments:refunded",[436,1255,1256,1257,1148,1259,1261],{},"A refund changed the payment (",[184,1258,652],{},[184,1260,643],{},").",[436,1263,1264],{},[184,1265,1218],{},[278,1267,1269],{"className":280,"code":1268,"language":282,"meta":283,"style":283},"type PaymentHookContext = { payment: PaymentDto }\n\ntype CheckoutBeforeContext = {\n  event?: H3Event\n  userId: number\n  reference?: { type: string, id: string }\n  params: Stripe.Checkout.SessionCreateParams   \u002F\u002F mutable\n}\n",[184,1270,1271,1290,1294,1305,1315,1323,1347,1370],{"__ignoreMap":283},[287,1272,1273,1275,1278,1280,1282,1284,1286,1288],{"class":289,"line":290},[287,1274,595],{"class":594},[287,1276,1277],{"class":598}," PaymentHookContext",[287,1279,602],{"class":308},[287,1281,376],{"class":308},[287,1283,909],{"class":315},[287,1285,319],{"class":308},[287,1287,914],{"class":598},[287,1289,926],{"class":308},[287,1291,1292],{"class":289,"line":312},[287,1293,661],{"emptyLinePlaceholder":660},[287,1295,1296,1298,1301,1303],{"class":289,"line":357},[287,1297,595],{"class":594},[287,1299,1300],{"class":598}," CheckoutBeforeContext",[287,1302,602],{"class":308},[287,1304,365],{"class":308},[287,1306,1307,1310,1312],{"class":289,"line":368},[287,1308,1309],{"class":315},"  event",[287,1311,690],{"class":308},[287,1313,1314],{"class":598}," H3Event\n",[287,1316,1317,1319,1321],{"class":289,"line":391},[287,1318,762],{"class":315},[287,1320,319],{"class":308},[287,1322,767],{"class":598},[287,1324,1325,1327,1329,1331,1333,1335,1337,1339,1341,1343,1345],{"class":289,"line":397},[287,1326,789],{"class":315},[287,1328,690],{"class":308},[287,1330,376],{"class":308},[287,1332,796],{"class":315},[287,1334,319],{"class":308},[287,1336,717],{"class":598},[287,1338,333],{"class":308},[287,1340,805],{"class":315},[287,1342,319],{"class":308},[287,1344,717],{"class":598},[287,1346,926],{"class":308},[287,1348,1349,1352,1354,1357,1359,1362,1364,1367],{"class":289,"line":709},[287,1350,1351],{"class":315},"  params",[287,1353,319],{"class":308},[287,1355,1356],{"class":598}," Stripe",[287,1358,226],{"class":308},[287,1360,1361],{"class":598},"Checkout",[287,1363,226],{"class":308},[287,1365,1366],{"class":598},"SessionCreateParams",[287,1368,1369],{"class":705},"   \u002F\u002F mutable\n",[287,1371,1372],{"class":289,"line":723},[287,1373,739],{"class":308},[159,1375,1376,1377,1379,1380,1382],{},"Transitions are conditional updates: a redelivered Stripe event emits nothing twice, and a ",[184,1378,616],{}," payment is never\ndowngraded by a late ",[184,1381,634],{}," event.",[273,1384,1386],{"id":1385},"routes","Routes",[409,1388,1389,1403],{},[412,1390,1391],{},[415,1392,1393,1396,1399,1401],{},[418,1394,1395],{},"Method",[418,1397,1398],{},"Path",[418,1400,73],{},[418,1402,429],{},[431,1404,1405,1427,1454],{},[415,1406,1407,1410,1415,1424],{},[436,1408,1409],{},"GET",[436,1411,1412],{},[184,1413,1414],{},"\u002Fapi\u002Fpayments",[436,1416,1417,1420,1421],{},[184,1418,1419],{},"requireUser",", scope ",[184,1422,1423],{},"payments:read",[436,1425,1426],{},"The signed-in user's payments.",[415,1428,1429,1432,1437,1444],{},[436,1430,1431],{},"POST",[436,1433,1434],{},[184,1435,1436],{},"\u002Fapi\u002Fpayments\u002Fresume",[436,1438,1439,1420,1441],{},[184,1440,1419],{},[184,1442,1443],{},"payments:write",[436,1445,1446,1447,1450,1451,1453],{},"Body ",[184,1448,1449],{},"{ paymentId }",". Returns ",[184,1452,535],{}," for an unpaid payment.",[415,1455,1456,1458,1463,1473],{},[436,1457,1409],{},[436,1459,1460],{},[184,1461,1462],{},"\u002Fapi\u002Fadmin\u002Fusers\u002F:id\u002Fpayments",[436,1464,1465,1468,1469,1472],{},[184,1466,1467],{},"users:admin:authorize"," (action ",[184,1470,1471],{},"view",")",[436,1474,1475,1476,1479],{},"Staff view of a user's payments, newest first. ",[184,1477,1478],{},"?limit="," defaults to 100, max 500.",[159,1481,1482,1483,1485,1486,1488,1489,1491],{},"Both user routes also accept bearer tokens and OAuth access tokens that carry the scope. The scopes are registered with\n",[163,1484,73],{"href":74}," as ",[184,1487,1423],{}," (\"Read your payments\") and ",[184,1490,1443],{}," (\"Resume your payments\").",[273,1493,1495],{"id":1494},"app","App",[409,1497,1498,1510],{},[412,1499,1500],{},[415,1501,1502,1505,1508],{},[418,1503,1504],{},"Export",[418,1506,1507],{},"Returns",[418,1509,499],{},[431,1511,1512],{},[415,1513,1514,1519,1524],{},[436,1515,1516],{},[184,1517,1518],{},"usePayments()",[436,1520,1521],{},[184,1522,1523],{},"{ payments, refresh, status, resume(paymentId) }",[436,1525,1526,1527,1530],{},"The signed-in user's payments; ",[184,1528,1529],{},"resume"," redirects to Stripe.",[159,1532,1533,1534,251,1536,1538,1539,1542,1543,1546,1547,1549,1550,1553,1554,1557],{},"With ",[163,1535,137],{"href":138},[163,1537,69],{"href":70}," installed, the module adds a ",[1540,1541,113],"em",{}," tab (order 20) and a\n",[1540,1544,1545],{},"Last payment"," card to the admin user page of ",[163,1548,133],{"href":134}," (",[184,1551,1552],{},"admin.users"," tab area,\n",[184,1555,1556],{},"admin.users.overview"," widget area).",[159,1559,1560,1561,1563,1564,1567,1568,1571,1572,1575,1576,1579,1580,1582,1583,1586,1587,1590,1591,1582,1594,251,1597,1600,1601,1604,1605,1608,1609,226],{},"The ",[1540,1562,113],{}," tab is a ",[184,1565,1566],{},"TableCard"," with a read-only ",[184,1569,1570],{},"UTable"," (amounts through ",[184,1573,1574],{},"useFormat().money",", status badges\ncoloured with ",[184,1577,1578],{},"statusColor","); there is no refund action yet, so rows have no menu. ",[1540,1581,1545],{}," is a ",[184,1584,1585],{},"SectionCard"," with\na ",[184,1588,1589],{},"DescriptionList",". On the admin dashboard, ",[1540,1592,1593],{},"Revenue, 30 days",[184,1595,1596],{},"StatCard",[1540,1598,1599],{},"Recent transactions"," a ",[184,1602,1603],{},"ListCard","\nthat links to the users list. All of them are built from the ",[163,1606,1607],{"href":32},"UX patterns"," of\n",[184,1610,1611],{},"@frigear-nu\u002Fui",[273,1613,1615],{"id":1614},"database","Database",[159,1617,1618,1619,1622],{},"One ",[184,1620,1621],{},"payments"," table.",[409,1624,1625,1637],{},[412,1626,1627],{},[415,1628,1629,1632,1634],{},[418,1630,1631],{},"Column",[418,1633,423],{},[418,1635,1636],{},"Notes",[431,1638,1639,1655,1671,1689,1705,1717,1732,1745,1757,1769,1781,1796,1810],{},[415,1640,1641,1646,1649],{},[436,1642,1643],{},[184,1644,1645],{},"id",[436,1647,1648],{},"text, primary key",[436,1650,1651,1654],{},[184,1652,1653],{},"pay_"," + random id.",[415,1656,1657,1662,1665],{},[436,1658,1659],{},[184,1660,1661],{},"userId",[436,1663,1664],{},"integer",[436,1666,1667,1668,226],{},"Indexed. No foreign key to ",[184,1669,1670],{},"users",[415,1672,1673,1678,1681],{},[436,1674,1675],{},[184,1676,1677],{},"status",[436,1679,1680],{},"text",[436,1682,1683,1686,1687,226],{},[184,1684,1685],{},"PaymentStatus",", default ",[184,1688,518],{},[415,1690,1691,1699,1702],{},[436,1692,1693,195,1696],{},[184,1694,1695],{},"amount",[184,1697,1698],{},"currency",[436,1700,1701],{},"integer, text",[436,1703,1704],{},"Minor units.",[415,1706,1707,1712,1715],{},[436,1708,1709],{},[184,1710,1711],{},"description",[436,1713,1714],{},"text, nullable",[436,1716],{},[415,1718,1719,1727,1729],{},[436,1720,1721,195,1724],{},[184,1722,1723],{},"referenceType",[184,1725,1726],{},"referenceId",[436,1728,1714],{},[436,1730,1731],{},"Indexed together.",[415,1733,1734,1739,1742],{},[436,1735,1736],{},[184,1737,1738],{},"checkoutSessionId",[436,1740,1741],{},"text, unique, nullable",[436,1743,1744],{},"Follows the new session after a resume. Null for invoice payments.",[415,1746,1747,1752,1754],{},[436,1748,1749],{},[184,1750,1751],{},"invoiceId",[436,1753,1741],{},[436,1755,1756],{},"Stripe invoice id for membership charges (see below).",[415,1758,1759,1764,1766],{},[436,1760,1761],{},[184,1762,1763],{},"paymentIntentId",[436,1765,1714],{},[436,1767,1768],{},"Indexed.",[415,1770,1771,1776,1778],{},[436,1772,1773],{},[184,1774,1775],{},"refundedAmount",[436,1777,1664],{},[436,1779,1780],{},"Default 0.",[415,1782,1783,1788,1791],{},[436,1784,1785],{},[184,1786,1787],{},"metadata",[436,1789,1790],{},"JSON, nullable",[436,1792,1793,226],{},[184,1794,1795],{},"Record\u003Cstring, string>",[415,1797,1798,1802,1804],{},[436,1799,1800],{},[184,1801,1115],{},[436,1803,1790],{},[436,1805,1806,1809],{},[184,1807,1808],{},"PaymentItem[]"," the session was created from; null for older rows.",[415,1811,1812,1823,1826],{},[436,1813,1814,195,1817,195,1820],{},[184,1815,1816],{},"paidAt",[184,1818,1819],{},"createdAt",[184,1821,1822],{},"updatedAt",[436,1824,1825],{},"timestamps",[436,1827],{},[1829,1830,1831,1832,226],"warning",{},"The module changes the generated schema, not the database: generate and commit a migration in every host app and\nfixture that uses it. See ",[163,1833,101],{"href":102},[273,1835,1837],{"id":1836},"membership-payments","Membership payments",[159,1839,1840,1841,1844,1845,191,1848,195,1851,195,1854,1857,1858,251,1861,1863,1864,1867,1868,1870,1871,1873,1874,1876,1877,1879],{},"When ",[184,1842,1843],{},"@frigear-nu\u002Fsubscriptions"," is installed next to this module, every membership invoice (",[184,1846,1847],{},"invoice.paid",[184,1849,1850],{},"invoice.payment_failed",[184,1852,1853],{},"invoice.voided",[184,1855,1856],{},"invoice.marked_uncollectible",") is stored as a payment with\n",[184,1859,1860],{},"referenceType: 'subscription'",[184,1862,1726],{}," set to the Stripe subscription id. They appear in the admin user\nPayments tab and Last payment card, fire the ",[184,1865,1866],{},"payments:*"," hooks (filter on ",[184,1869,1723],{},") and are returned by the\n",[184,1872,479],{}," MCP tool. Refunds are applied like any other payment through ",[184,1875,205],{},". Without this module,\n",[184,1878,1843],{}," behaves as before and records nothing. Zero-amount invoices (trials, full discounts) are skipped, and only invoices\nreceived after upgrading are stored.",[159,1881,1882,1885],{},[184,1883,1884],{},"recordInvoicePayment(input: InvoicePaymentInput)"," is the auto-imported server util behind this; it is idempotent per\ninvoice id.",[273,1887,93],{"id":1888},"mcp",[159,1890,1891,1892,1895,1896,1898,1899,1901,1902,1905,1906,251,1908,1910,1911,1914,1915,1917],{},"Set ",[184,1893,1894],{},"settings.mcp: true"," to expose ",[184,1897,479],{}," (scope ",[184,1900,1423],{},"): the signed-in user's own payments, newest\nfirst, with an optional ",[184,1903,1904],{},"limit",". ",[184,1907,1695],{},[184,1909,1775],{}," are in whole currency units (",[184,1912,1913],{},"52.2"," = 52.20), not minor units, and ",[184,1916,1698],{}," is upper-case.",[273,1919,1921],{"id":1920},"translations","Translations",[159,1923,1924,251,1927,1930,1931,1934,1935,1938,1939,1942,1943,1945,1946,251,1949,1952,1953,1956,1957,1961],{},[184,1925,1926],{},"da",[184,1928,1929],{},"en"," locale files are registered with ",[163,1932,101],{"href":1933},"\u002Fmodules\u002Fmodule-kit#translations-i18n"," under ",[184,1936,1937],{},"payments.*",":\n",[184,1940,1941],{},"payments.status.\u003Cstatus>"," (one key per ",[184,1944,1685],{},"), ",[184,1947,1948],{},"payments.defaultDescription",[184,1950,1951],{},"payments.admin.*"," for the\nadmin tab. API error messages stay English. Override keys in your app's ",[184,1954,1955],{},"i18n\u002Flocales\u002F\u003Ccode>.json"," (see\n",[163,1958,1960],{"href":1959},"\u002Fmodules\u002Fmodule-kit#overriding-module-strings-in-your-app","overriding module strings","):",[278,1963,1967],{"className":1964,"code":1965,"language":1966,"meta":283,"style":283},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{ \"payments\": { \"status\": { \"partially_refunded\": \"Partly refunded\" } } }\n","json",[184,1968,1969],{"__ignoreMap":283},[287,1970,1971,1974,1977,1979,1982,1984,1986,1988,1990,1992,1994,1996,1998,2000,2002,2004,2006,2009,2011,2013,2015],{"class":289,"line":290},[287,1972,1973],{"class":308},"{",[287,1975,1976],{"class":308}," \"",[287,1978,1621],{"class":594},[287,1980,1981],{"class":308},"\"",[287,1983,319],{"class":308},[287,1985,376],{"class":308},[287,1987,1976],{"class":308},[287,1989,1677],{"class":598},[287,1991,1981],{"class":308},[287,1993,319],{"class":308},[287,1995,376],{"class":308},[287,1997,1976],{"class":308},[287,1999,652],{"class":384},[287,2001,1981],{"class":308},[287,2003,319],{"class":308},[287,2005,1976],{"class":308},[287,2007,2008],{"class":328},"Partly refunded",[287,2010,1981],{"class":308},[287,2012,812],{"class":308},[287,2014,812],{"class":308},[287,2016,926],{"class":308},[2018,2019,2020],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":283,"searchDepth":312,"depth":312,"links":2022},[2023,2024,2025,2026,2027,2028,2029,2030,2031,2032],{"id":275,"depth":312,"text":276},{"id":406,"depth":312,"text":407},{"id":483,"depth":312,"text":484},{"id":1154,"depth":312,"text":1155},{"id":1385,"depth":312,"text":1386},{"id":1494,"depth":312,"text":1495},{"id":1614,"depth":312,"text":1615},{"id":1836,"depth":312,"text":1837},{"id":1888,"depth":312,"text":93},{"id":1920,"depth":312,"text":1921},"One-time Stripe payments - Checkout sessions with inline prices, a payments table, refunds and lifecycle hooks driven by verified Stripe events.","md",null,{},{"title":113,"description":2033},"22O-MUo8QIlP34vXMP-gACIdB0rmk3U1_mlMyIj-zqs",[2040,2042],{"title":109,"path":110,"stem":111,"description":2041,"children":-1},"Let users sign in to your applications through an OAuth 2.0 \u002F OpenID Connect server, with roles and claims supplied by the host app.",{"title":117,"path":118,"stem":119,"description":2043,"children":-1},"Typed per-user preferences that modules and the host app register, stored on the user and optionally forwarded to OAuth applications as claims.",1792824488450]