跳转到内容
彼岸论坛

小天管理

管理员
  • 内容数

    15407
  • 注册日期

  • 最后上线

  • 得奖次数

    1

小天管理 发表的所有内容

  1. https://github.com/StevenSLXie/early_retirement_in_sg/blob/main/%E5%9C%A8%E6%96%B0%E5%8A%A0%E5%9D%A1%E6%8F%90%E5%89%8D%E9%80%80%E4%BC%91.md
  2. 增加了对包括思维导图在内的十九种图表绘制的 Markdown 语法支持 提供所有图表的黑白配色主题(Ctrl + Alt + Y) 所有十九种图表可以在 PDF 文件中原样下载输出。 详细十九种绘图参见: https://www.zybuluo.com/ghosert/note/2560850
  3. 你们有遇到吗,咋个取消,我看设置有 url 屏蔽,但是微信支付拉起的窗口不知道 url 有什么办法能屏蔽吗
  4. SaaS 产品集成 Stripe 支付的一些坑 最近在给自己的 SaaS 产品 PPResume 集成支付,调研了很久,最终还是决定用 Stripe ,集成过程中又发现了一些坑,分享出来,供后来者参考。 四种集成方式的选择 Stripe 官方提供四种主流的集成方式: payment links:最简单的一种,集成成本最低,时间最快,但是可定制化程度最低,比较适合简单的业务 checkout ,又分为 hosted checkout 和 embedded checkout 两种: hosted checkout:用户在 checkout 时,需要重定向到 stripe 的网站,好比说你在淘宝买东西付款时,需要重定向到支付宝或者微信支付的网站,用户流程更长一些,集成成本也不算高,比较简单 embedded checkout:stripe 提供一个内嵌的 form ,可以直接嵌入到你的网站中,这样用户在 checkout 时,不需要重定向到 stripe ,用户体验会更好一些,集成成本比 hosted checkout 高很多,我个人开发过程中的一个 demo elements:定制化最强的一种,同时也是成本最高的,所有的元素,诸如信用卡输入框这些均可定制,适合高度复杂的业务,不建议普通用户使用 Next.js 官方有一个 demo,可以直观对比下 payment links 、checkout 和 elements 三种方式的区别 我个人建议: 如果是极其简单的业务,或者开发时间、能力有限,用 payment links 就行,比如说你在网上卖电子书、软件 license ,放个 payment links ,收到 payment 后,给 customer 自动或者手动发送电子书、软件 license 就行了; payment links 还有一个显著的优点,就是因为 payment links 本身提供的是一个 URL ,你可以把这个 URL 分享到各种平台,就如我们日常在用的二维码收款码一样 如果略复杂一些的业务,比如有多种 pricing plan ,可以用 checkout ,想要最佳的用户体验,又能承担高一些的开发成本,可以用 embedded checkout ,但是 checkout 有个关联 customer 的小坑,后面说 elements 不建议采用,开发成本过高了 Pricing Table 的问题 Stripe 提供一个 no code 的 pricing table,可以方便的在自己的网站上嵌入一个 pricing table 。但是 Stripe 的 pricing table 有一个问题,就是默认点击 Subscribe button 的时候,是直接定向到 stripe 的 checkout 页,而对一般的 SaaS 产品而言,Pricing Table 的 CTA button 针对用户是否已经登录,要定向到不同的页面: 如果用户尚未注册登录,则直接重定向到用户的注册登录页,引导用户注册登录 如果用户已经登录,则按照正常的流程,重定向用 subscribe 付款页面 Stripe 的 Pricing Table 另一个问题就是 UI 的可定制性还是差了一些,没有提供单独的 CSS 定制,可能和产品本身的 UI 风格有较大差异。 海外有一个专门的 Pricing Table SaaS 产品,部分解决了这个问题,可以参考一下。实在不行,Pricing Table 就还是自己写的,不难的。 Checkout 最好关联 Customer Stripe Checkout Session 在创建 时,接收一个 customer 参数,该参数是 stripe 内建的 customer 的 id ,如果创建 Stripe Checkout Session 时(stripe.checkout.sessions.create),没有提供这个 customer 参数,那么 Stripe 的后台会将所有 email/credit card/phone 相同的 customer 统一归组成一个 guest customer ,这个 guest customer 仅仅在 Stripe Dashboard 中可见,而在 Stripe API 中是不可见的,并且 guest customer 没有办法对接 Customer Portal (关于 Customer Portal ,见后文)。 我个人建议: 在创建 stripe checkout session 时,先创建 stripe customer ,但是不要用一个 customer email 创建多个 Stripe customer ,最后确保一个 customer email 创建并且仅创建一个 Stripe Customer ,code 类似于这种: /** * Retrieves or creates a Stripe customer with logto user's email. * * This function first attempts to fetch the user's context from the Logto * client using the provided request. * * Then checks if a customer already exists in Stripe with that email, if * existed, return that stripe customer, otherwise a new customer is created in * Stripe. * * @param {NextRequest} request - The incoming request object from Next.js. * * @returns {Promise<Stripe.Customer | null>} A promise that resolves to the * Stripe Customer object if found or created, otherwise null. */ export async function getOrCreateCustomer( request: NextRequest ): Promise<StripeServer.Customer | null> { const stripe = getStripeServer() try { // find a way to get a customer email from your auth system const customerEmail = 'customer@ppresume.com' // This is not likely to happen as all logto users should have a valid email if (!customerEmail) { return null } const customers = await stripe.customers.list({ email: customerEmail, limit: 1, }) if (customers.data.length === 0) { return await stripe.customers.create({ email: customerEmail, metadata: { logtoUserId: user?.claims!.sub, }, }) } else { return customers.data[0] } } catch (err) { return null } } Customer Portal 集成的两种方式 Stripe 提供一个 no code 的 Customer Portal,可以让用户自行管理支付相关的数据,比如支付方式,订阅记录,invoices 等等,这些东西自己实现,又繁琐又无聊,因此如果支付系统能提供相应的解决方案,还是很方便的。 据我所知,Stripe 和 LemonSqueezy 是提供 customer portal 的,而 Paddle 是不提供的(有一个专门的 SaaS 产品就是给 Paddle 提供一个 Customer Portal )。 集成 Stripe Customer Portal 有两种方式: 一种是通过 no-code 的方式,在 Stripe Dashboard 中直接 activate customer link ,拿到一个 URL ,将这个 URL 放到你的网站中,用户访问这个 URL ,就可以用验证码登录来访问或管理支付相关的信息 另一种是通过 API 的方式,在用户访问 customer portal 时,通过 API 临时创建一个 customer portal 的 URL ,然后把这个临时 URL 返回给用户,用户通过这个临时生成的 URL 访问 customer portal ,代码大略如下: /** * Creates a Stripe customer portal session and redirects user to that portal * * It first retrieves or creates a Stripe customer based on the incoming * request, then generates a session for the Stripe Billing Portal, and finally * redirects the user to the Stripe Billing Portal. * * The major benefit of using API to create a customer portal with customer * attached over plain customer portal link provided from stripe dashboard is, * user won't need to manually sign in for API created customer portal. * Basically, when you create a customer portal with API, it will generate a * short-lived URL for user and this URL do not need user to sign in. * * From [Stripe]( https://docs.stripe.com/api/customer_portal/sessions): * * ``` * A portal session describes the instantiation of the customer portal for a * particular customer. By visiting the session’s URL, the customer can manage * their subscriptions and billing details. For security reasons, sessions are * short-lived and will expire if the customer does not visit the URL. Create * sessions on-demand when customers intend to manage their subscriptions and * billing details * ``` * * @param {NextRequest} request - The incoming request object from Next.js. * * @returns {Promise<Response>} A promise that resolves to a redirect response * to the Stripe Billing Portal, or a JSON response indicating that the customer * was not found. */ export async function GET(request: NextRequest) { const stripe = getStripeServer() const customer = await getOrCreateCustomer(request) if (!customer) { return Response.json( { message: 'Customer not found', }, { status: 404 } ) } const customerPortalSession = await stripe.billingPortal.sessions.create({ customer: customer.id, return_url: getAbsoluteUrlWithDefaultBase(routes.pages.settings.billing), }) return Response.redirect(customerPortalSession.url, 303) } 第二种方式最大的好处就是,用户不必通过验证码来登录 customer portal ,而是可以直接访问,用户体验要好太多。 Stripe Webhook 实现 用户下单之后,系统需要满足用户的下单需求,比如如果是实物电商,那么商家需要打包发货,而如果是 SaaS 这种虚拟服务,则一般需要赋予用户相应的 Pro 权限,这个过程叫做 order fulfillment。 Order fulfillment 需要实现 webhook: Webhooks are required You can’t rely on triggering fulfilment only from your Checkout landing page, because your customers aren’t guaranteed to visit that page. For example, someone can pay successfully in Checkout and then lose their connection to the internet before your landing page loads. Set up a webhook event handler to get Stripe to send payment events directly to your server, bypassing the client entirely. Webhooks are the most reliable way to know when you get paid. If webhook event delivery fails, we retry several times. 所谓 webhook ,简单讲,就是在你的系统中向公网暴露出一个 API endpoint ,当用户通过 Stripe 下单成功后,Stripe 给这个 API endpoint 发送一个 POST 请求,请求 event 里包括详细的下单付款信息,你的系统收到这个信息后决定怎样给用户赋予相应的权限等等。 Webhook 实现中有一个小坑,就是 Stripe 不保证 event 的时序性,也不保证请求的唯一性——事实上,公网的网络请求中也是没有办法做到这一点的,因此你的 Webhook 实现中,看需求,如果对数据一致性要求比较高,最好实现幂等性。具体细节不在这里讲啦。 后话:集成 Stripe 花了小一个月的时间,Stripe 的开发体验非常不错,但是产品矩阵很庞大,新手往往比较容易困惑,再就是有一些隐藏的坑,我遇到了一些,随手记了下,发上来当一个备份吧。 集成支付系统还是蛮耗体力的一个活,后面有时间的话,打算写一篇《 Stripe 101:The Missing Tutorial for Indie Makers 》。 最后打个小广告哈,我的 SaaS 产品 PPResume 去年上线后又经过一年的打磨,最近终于要推出付费计划啦,所有在支付正式上线之前注册的用户,都将获得一年内 50% off 的折扣,欢迎注册体验。
  5. 黑神话就剩一个杨戬没打了,昨天去网鱼发现黑神话云同步一直失败,网上的办法基本上都用了一遍(包括换地区,离线模式再上线等),也换了加速器和代理都不行。然后我就想去 steam 网站上单独下载存档放到本地,还是提示下载失败。 第一个文件下载提示服务不可用,第二个文件能正常下载,第三个文件报错 有什么好的解决方法吗?
  6. 请不要说 covid 请不要说原神,那只是一款游戏,而且其中包含多少中国文化的东西我不知道 请不要说猿神,它确实都是中国文化,但是毕竟只是一款游戏
  7. 基本是公园里慢走、慢跑、家里独处,不会刻意提高音量。请问这种情况下,骨传导耳机 or 挂脖子的小音箱,会伤害听力吗?
  8. 最近一对夫妻在附近新开了一家早餐店,因为近,我开始常在那吃肠粉,大概一两个星期之后,老板逐渐主动和我打招呼聊了起来 首先说明一下,我属于不擅长社交的人,而他们是自来熟,经常和顾客聊天。 直到有次问到我是哪里人,发现我们的家乡是同一个地级市,此后便称呼我老乡,并且他开始改用方言和我交流 然而,我其实不太愿意和老板过多交谈,之前也遇到过类似的情况,老板热情过头,问一些工作和生活上的问题,而现在他们也是如此,尤其喜欢在顾客少时找我聊天,我也已经习惯说普通话了,方言已经有些陌生,尽管我们是同一个地级市的人,但不同县的方言也有差异 最近,我打算自己做早餐,主要是因为我觉得肠粉没什么营养,其次是因为我不喜欢跟老板打招呼,说方言也让我感到莫名的压力 但我脸皮薄,我担心要是不去他们店里吃早餐,不知道老板会怎么想我 每次走那条路,经过他们店时,如果被他们看见,都会和我打招呼“老乡……”,让我感觉很难避免再次与他们打交道 其实,如果我们不熟,我不再去吃早餐也不会有任何心理负担……目前这种不由自主的过度熟络,让我现在的处境有些尴尬 请问大家,这种情况下应该怎么处理呢?谢谢!
  9. alist 的电报群看到有人在发
  10. 小学生的科技节作业,要求是不能始于套件,手工制作,不添加额外的重量,有什么好的制作建议 具体要求看下面的图片,imgur 图床
  11. 在麦当劳,被两位约 60 岁的阿姨问,手机安装不了软件怎么办。 我看了下,是华为手机,需要登录华为账户才能安装软件。 解决这个问题后,过会她们又来问我,另一个软件安装不了。 这时我有点敏感了:她先要下载的,是一个端到端私聊的 IM 软件(名字我就不说了),总之应该是可以绕过监管的。第二次装不上的软件,是叫什么「 XX 娱乐」,听名字就不正经(后来搜索了下,是明显的菠菜软件)。我明白是怎么回事,应该是链接被墙了。 我问她链接是怎么来的,她说是公司发的,我估计就是刚才那个聊天软件里发的。这时我几乎可以肯定,她们涉及电诈、或者其他灰色的东西,自然不会再提供帮助。 她们已经折腾了快一小时。是什么样的动力,能让她们费这么大劲,去折腾这个东西,估计就是赚钱了。远远听她们聊天,有买 U 、钱打过去、账单截图给他… 我后来又过去问,这是什么事、不会是诈骗吧?她说:不会, 我都赚了十几万了,你要不要试试?好吧,我就不说什么了… 第一次在身边见到这种事。
  12. 由于备份及容灾意识过强,我整了 3 台设备。 iPad mini 5 iPhone 13 mini iPhone 13 都装有 1Password 。 想着,哪怕其中一个故障或者丢失了,都没有任何问题。 就这样愉快的过了 2-3 年。 唯一发现的问题是, 同时充电,桌上一堆线。还有 Mac ,耳机,充电宝。 得多配几个充电头。 影响不大,可以处理,也可以忽略。 时间来到了本月初,一个闲的无聊的周末。 我把 3 台设备都出了,换了个 iPhone 15 。 Type-C ,爽了。 还可以直连三星 T7 硬盘,更爽了。 故事从这里就开始了。 旧设备退 ID ,密码是自动生成的,不记得。 拿张纸写下来了。 这里看似是救命稻草,其实不写也没事。 1Password 得转移到新机上,因为所有的密码都在上面。 用 Dropbox 同步,200 多个。 什么 2FA ,什么备用代码,通通都记在里面。 1Password 保险库保存在 Dropbox 里面, Dropbox 的 2FA ,备用代码,都保存在 1Password 保险库里面。 我想要拿到 2FA ,得先连上保险库。 看到没有,这里死循环了。 其实我早就发现死循环了,但这不有 3 台物理备份嘛,死不了。 开始换新机。 期间,什么都不用做,数据转移好了。 系统是 iOS 18 ,可以用。 瞅一眼,1Password 中 200 多个密码都在。 回家把线捋一捋,多出的充电头收起来。 整个房间清静了。 划拉了几下 iOS 18 ,发现很多设置没有。 还是换回 iOS 17 吧,懒得折腾。 搜了一下,用 Mac 可以降级。 那等什么,来吧。 自然是先点备份,再降级。 瞅一眼,确实备份了。 开始降级。 期间,什么都不用做,数据转移好了。 仔细一看,不对,确实是回到了 iOS 17 ,但 1Password 没了。 没事,我不是备份了吗。 点一下的事儿,点恢复备份。 没错,你推理到了。 恢复不了。 这下进入死循环了,死得透透的。 你们有过一瞬间丢失 200 多个密码的经历吗? 或者我换一个问法, 你们的心死过吗? 我这种各种网盘都有,数据交叉备份。 密码全部自动生成,带 2FA 。 横行墙头 10 余年,从无任何闪失的独行剑客。 今天,栽了。 我的心仿佛空了一块, 更让人伤心的是, 我不知道我空掉的这一块,是个啥。 因为我不记得。 总不能马上就去死, 新手机还在充电呢。 应该还有救,捋一捋。 一个个来。 Apple ID 我能登录,其实不手写密码也没事。 开了双重认证,能收短信就能登录。 这点相当简单,也相当好。 就是这点救了我,不然我绝不可能发这个帖。 因为我的心死了。 不是,因为我登录不了。 这下好办了。 我有另外两个 Apple ID ,专门用来做所有账号的辅助邮箱。 是的,我有好几个 Apple ID ,用处各不相同。 密码自然也不记得,但我能收到短信,就能登录了。 我复活了。 有印象的数据全部回来了。 当然有我不记得的,不仅密码不记得, 我连帐号都不记得,甚至登录地址我都不记得。 等于是某些东西,从我的生命里消失了。 是哪些东西消失了,我也不知道。 仿佛从来就不曾来过。 有影响吗? 完全没有。 倒是有一些结论。 Dropbox 我是很喜欢的,存了很多重要数据。 帐号邮箱我找回了,能收到邮件。 Dropbox 密码也重置了,但无法登录。 卡在了 2FA 和备用代码上。 不让我登录,我拿不到这两个数据。 发了一堆邮件找客服,他扯一堆废话,就是登录不了。 得,不要了。 除了 1Password 保险库,其他所有数据都有交叉备份。 没啥影响。 还是 Apple 和 Google 简单纯粹, 双重认证短信一填,这个帐号就恢复了。 辅助邮箱验证码一填,这个帐号就恢复了。 至于这个帐号是不是持有人恢复的, 作为数据商,你应该去分析。 我看到,Apple 和 Google 做了分析。 他并非马上恢复, 而是告诉我,他需要经过分析,才能判定是否给我恢复。 这点做得非常好。 而不是如 Dropbox ,给我发一份备用代码,叫我打印出来。 没有这个备用代码,不给我登录。 你想啥呢? 还打印? 就算打印了,我能找得到? 滚犊子。
  13. 主题色 violet 主题色 red 主题色 stone 主题色 lime 链接 项目链接: https://github.com/hanyujie2002/Vardar 示例网站: https://vardar-example.xyz/ 中文文档链接: https://github.com/hanyujie2002/Vardar/blob/main/README-zh.md 以后还会不断完善本项目,感谢你的支持🐱
  14. 电信宽带,申请了公网 ip 发现只有 ipv4 公网,没有 ipv6 。 我想使用 moonlight+sunshine 远程,这样的话无法远程,咋办呢,有没有老哥给个建? (联系电信客服好像就是死活不给 ipv6 ) 目前只能用向日葵远程,说实话体验挺差的,prasec 之前可以用现在被墙了。
  15. 阳台沦陷了
  16. 前天手贱更新了 btiwarden ,safari 上点 bitwarden 解锁,就一直转菊花,重装也是一样的问题,现在没法用了😓 chrome 和 bitwarden 的应用程序倒是好的,只有 safari 上不能使用,就是无法进入登录的界面,用了各种代理也不行。有人知道怎么回事吗? 我是 Monterey12.6.1 MBA 16G M1
  17. 现在需要做一个设备授权的功能,但是不知道怎么实现,各位大佬有做过的吗 怎么识别的设备,怎么做到的设备授权
  18. 4k hdr 挺清晰的。 世界各地,大部分都有。 我看了东京的、曼谷的、台湾、新加坡的、马来西亚、印尼的、三里屯的、香港的、巴西、圣地亚哥。 好像繁华地带都差不多,都类似三里屯,或者反过来,三里屯类似其他地方。 摄像头是头戴式,或者胸戴式,非航拍。
  19. 换了新手机,太相信手机搬家,结果只是把应用迁移到新手机,数据没有迁移,旧手机是依旧换新,并且以已经格式化了, 现在的问题是记得 authy 的备份密码,肯定不会错的,但是 authy 总是显示密码错误 请问有万能的大神们有解决方案吗?现在几十个网站无法登录,但是这些网站的紧急备用密码也没有备份 authy 的机制是不会上传备份密码到他们的服务器~ 真心求大神门提供一下思路或者方法 万分感谢!
  20. 对于如何设计新的聊天界面,有了一些想法,分享给大家:
  21. 用户的照片还是蛮敏感的,这么大的问题监管会罚一下吗?然后赔偿道歉什么的?
×
×
  • 创建新的...