golang、laravel对接stripe海外支付接口的总结和流程(通俗易懂)

目录

stripe是什么?

环境

配置后台

首先让管理员把你设置成为开发者

然后进入后台

然后你要创建产品,开单周期要写每天,我这里理解成每天都会有人买的

获取产品id

获取密钥,后续代码需要用到

支付代码

唤起支付页面

测试的信用卡号

添加端点webhook

stripe后台配置

非常注意的地方

处理回调代码

golang代码(自己测试用的,go的程序员可以看看)

最后,怎么找到他们的技术支持呢?


stripe是什么?

我们国内有支付宝、微信、银联,国外就有stripe,但是他们是信用卡的。

据我探索,有以下支付方式

  1. Checkout Session 文档位置:https://docs.stripe.com/api/checkout/sessions
  2. payment links  文档位置: https://docs.stripe.com/api/payment_links/payment_links
  3. credit notes 文档位置:https://docs.stripe.com/api/credit_notes/object

注意:我们用checkout session

环境

PHP:7.2

框架:laravel 5.5以上都行

compose包:

composer require stripe/stripe-php

配置后台

我们在开始前,要清楚stripe的流程,他们的流程跟我们国内是完全不一样的。

首先让管理员把你设置成为开发者

然后进入后台

点产品目录,再点测试模式,在测试模式下,是不会产生付费的,都是虚拟的,大家可以放心

然后你要创建产品,开单周期要写每天,我这里理解成每天都会有人买的

获取产品id

获取密钥,后续代码需要用到

支付代码

#配置刚刚后台获取到的密钥
STRIPE_KEY=sk_test_5
use App\Http\Controllers\CIAesController;
use App\Http\Controllers\Controller;
use App\Model\OrdersModel;
use App\Model\ProductModel;
use App\Model\UsersModel;
use App\Model\VerifyCodesModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Redirect;
use Stripe\Stripe;
use Stripe\StripeClient;//创建商品public function createProduct(Request $request){$vip_tag = $request->input('vip_tag');
//        $product_id  = 'prod_Q9V9Ypb6KFF4M4';
//        $order_id    = '29101d2d';
//        $goods_price = 1;try {$userInfo = $this->getUserInfoServer();if (!isset($userInfo['id']) || !$userInfo['id']) {throw new \Exception('当前未登录,请先登录', 9000);}if ($userInfo['type'] != 2) {throw new \Exception('请用邮箱登录再支付', 9000);}if ($userInfo['expiratio_date'] >= date('Y-m-d H:i:s')) {throw new \Exception('会员只支持购买一个');}$productInfo = ProductModel::where('vip_tag', $vip_tag)->first();if (!$productInfo) {throw new \Exception('暂无价格');}$product_id  = $productInfo->product_id;$order_id    = 'qw' . date('YmdHis') . time() . mt_rand(1000, 9999);$goods_price = $productInfo->price;// 创建订单OrdersModel::insert(['user_id'     => $userInfo['id'],'transfer_no' => $order_id,'amount'      => $goods_price,'product_id'  => $product_id,'status'      => 3,]);$url = $this->create_price($product_id, $order_id, $goods_price, 0);return Redirect::to($url);// 重定向去支付} catch (\Exception $e) {Log::error('createProduct', ['msg'  => $e->getMessage(),'file' => $e->getFile(),'line' => $e->getLine(),]);if ($e->getCode() == 9000) {return redirect('home/login');}return back()->withErrors([$e->getMessage()])->withInput();}}/**** 创建价格* @param $product_id 产品id* @param $order_id 业务系统的订单id* @param $goods_price* @param $is_source 订阅用到的* @return string|null* @throws \Stripe\Exception\ApiErrorException*/public function create_price($product_id, $order_id, $goods_price, $is_source){//获取订单对应的商品价格
//        $goods_price = \db('order')->where('id', $order_id)->value('pay_money');$_key      = env('STRIPE_KEY');// 你的私钥$stripe    = new StripeClient($_key);$price_arr = $stripe->prices->create(['unit_amount'  => $goods_price * 100,//'unit_amount' => 1*100,'currency'     => 'usd','tax_behavior' => 'exclusive',//'recurring' => ['interval' => 'day'],'product'      => $product_id,'metadata'     => ['order_id' => $order_id],]);//print_r($price_arr->id);die;return $this->actionStripe($price_arr->id, $order_id, $is_source);}/*** 创建stripe支付* @param $price_id 产品id* @param $order_id 业务系统订单id* @param $is_source 订阅用到的* @return string|null* @throws \Stripe\Exception\ApiErrorException*/public function actionStripe($price_id, $order_id, $is_source){$_key = env('STRIPE_KEY');$domain = 'xxx';// 要回调的域名//如果是AI订阅和AI作品打样的话if ($is_source == 8 || $is_source == 9) {$cancel_url  = '';$success_url = '';} else {$cancel_url  = $domain . '/home/actionNotify';$success_url = $domain . '/home/index';}// stripe 生成订单Stripe::setApiKey($_key);$checkout_session = \Stripe\Checkout\Session::create(['line_items'  => [['price'    => $price_id, // 产品id'quantity' => 1,],],'mode'        => 'payment','success_url' => $success_url,// 同步回调'cancel_url'  => $cancel_url,// 异步回调//            'automatic_tax' => [//                'enabled' => false,// 设置为true就要开通税务,会提示Stripe Tax has not been activated on your account. Please visit https://stripe.com/docs/tax/set-up to get started//            ],'metadata'    => ['order_id' => (string)$order_id,],]);Log::info('', ['ses' => $checkout_session, 'id' => $checkout_session->id]);return $checkout_session->url;}

唤起支付页面

当你调用完支付代码,会重定向到stripe支付界面

测试的信用卡号

因为我们是测试环境,这时候支付要用他们提供的测试信用卡号,那么这个卡号在哪里拿的呢?

点链接文档: https://docs.stripe.com/testing

stripe提供了好多信用卡给我们做测试的

添加端点webhook

这时候,我们创建完订单,如果用户支付完成,怎么回调呢?就比如我们支付宝、微信这些支付,都是要回调业务系统的订单号的

我们在上面的代码中,通过metadata来传递了订单号了,那么怎么接受他呢?没错,就是异步回调,stripe的异步回调叫做webhook

stripe后台配置

异步回调地址:http://xxxxx/home/actionNotify

非常注意的地方

一定要注意了我们用的是Checkout:Session方式

所以在添加webhook的时候,要选择checkout的,否则你会接受不到metadata元数据,这里面的订单号

处理回调代码

public function actionNotify(Request $request){Log::info('asdas', ['all' => $request->all()]);$data = $request->input('data', []);$type = $request->input('type', '');$payload = @file_get_contents('php://input');try {if (!isset($data['object']) || !$data['object']) {throw new \Exception('参数有误');}$event = \Stripe\Event::constructFrom(json_decode($payload, true));switch ($event->type) {case 'checkout.session.completed':$succeeded = $event->data->object;$content = "=========".date('Y-m-d H:i:s',time())."==========\r\n";$content .= json_encode($succeeded);Log::info('content=======' . var_export($content, true));if ($succeeded->status == 'complete') {$order_id = $succeeded->metadata->order_id;// 处理支付成功逻辑$orderInfo = OrdersModel::where('status', 3)->where('transfer_no', $order_id)->first();try {if (!$orderInfo) {throw new \Exception('暂无订单');}$userInfo = UsersModel::where('status', 1)->where('id', $orderInfo->user_id)->first();if (!$userInfo) {throw new \Exception('没有此用户');}$productInfo = ProductModel::where('status', 1)->where('product_id', $orderInfo->product_id)->first();if (!$productInfo) {throw new \Exception('没有这个产品');}DB::beginTransaction();$productInfo->period = $productInfo->period + 1;$expiratio_date = date('Y-m-d', strtotime("+ $productInfo->period day"));$userBool       = UsersModel::where('id', $userInfo->id)->update(['expiratio_date'    => $expiratio_date,'day_search_number' => $productInfo->day_search_number + $userInfo->day_search_number,'vip_tag'           => $productInfo->vip_tag,]);if (!$userBool) {throw new \Exception('修改用户表失败');}$orderBool = OrdersModel::where('id', $orderInfo->id)->update(['status' => 1]);if (!$orderBool) {throw new \Exception('修改订单表失败');}DB::commit();} catch (\Exception $e) {DB::rollBack();Log::error('增加权限失败', ['msg'       => $e->getMessage(),'line'      => $e->getLine(),'file'      => $e->getFile(),'orderInfo' => $orderInfo,]);}}break;case 'checkout.session.async_payment_failed':Log::info('pay is failed');break;default:echo 'Received unknown event type ' . $event->type;break;}} catch(\UnexpectedValueException $e) {// Invalid payloadhttp_response_code(400);Log::error('actionNotify', ['msg'  => $e->getMessage(),'file' => $e->getFile(),'line' => $e->getLine(),'all'  => $request->all(),]);return false;}}

golang代码(自己测试用的,go的程序员可以看看)

package controllerimport ("fmt""github.com/gin-gonic/gin""github.com/stripe/stripe-go""github.com/stripe/stripe-go/checkout/session""log""os"
)func Stripe(c *gin.Context)  {stripe.Key = "sk_test_51PGi4mRsyk2oxMEtA88eCI12KXZl87r8GsZx0AJ0xcdA7mLaGBq4MHQPHTSsl3ocGEBZHpkko773UEaCGXjfPlKC00XNesU7YX"lineItem := &stripe.CheckoutSessionLineItemParams{Quantity:     stripe.Int64(1),            // 数量Amount: stripe.Int64(100),Currency: stripe.String("usd"),Name: stripe.String("测试商品"),// 可以添加其他可选字段,比如 Description、Images 等}lineItems := []*stripe.CheckoutSessionLineItemParams{lineItem}params := &stripe.CheckoutSessionParams{SuccessURL: stripe.String("http://www.example.com/success"),CancelURL:  stripe.String("https://more.esnewcollege.com/api/enterprise/wechat/mhCallback"),PaymentMethodTypes: stripe.StringSlice([]string{"card",}),Mode: stripe.String("payment"),LineItems: lineItems,}params.Metadata = map[string]string{"order_id":"123",}// 创建付款Sessions, err := session.New(params)if err != nil {log.Fatalf("Error creating Checkout Session: %v", err)}// 输出付款链接url := "https://checkout.stripe.com/c/pay/" + s.ID + "#fidkdWxOYHwnPyd1blpxYHZxWjA0VUJsMWhXdnxuN2p9SEBxYkltRkpGcn9GT2NAQHxcXDVGakFDYE9pdDFda3dXXHNwSUpDbzdkT2tmPGZmcEpIaURPU0JJdk89Yk13Nl9ddlVMV1c2TDM2NTUxclRuaEtydicpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBabHFgaCcpJ2BrZGdpYFVpZGZgbWppYWB3dic%2FcXdwYHgl"fmt.Fprintf(os.Stdout, "付款链接: %v\n", url)
return
}

最后,怎么找到他们的技术支持呢?

全程英文交流

文档位置:https://support.stripe.com/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/16641.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

甘肃省大学生志愿服务西部计划报名流程及免冠证件照处理

在甘肃省,大学生志愿服务西部计划是一项旨在鼓励和引导大学生参与西部地区社会服务与发展的重要项目。随着2024年报名季的到来,许多有志青年正准备投身这一有意义的事业。本文将详细介绍报名流程,并提供免冠证件照的处理技巧,帮助…

设计模式11——代理模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用,主要是下面的UML图可以起到大作用,在你学习过一遍以后可能会遗忘,忘记了不要紧,只要看一眼UML图就能想起来了。同时也请大家多多指教。 代理模式(Proxy&am…

每日AIGC最新进展(12):在舞蹈视频生成中将节拍与视觉相融合、Text-to-3D综述、通过内容感知形状调整进行 3D 形状增强

Diffusion Models专栏文章汇总:入门与实战 Dance Any Beat: Blending Beats with Visuals in Dance Video Generation https://DabFusion.github.io 本文提出了一种名为DabFusion的新型舞蹈视频生成模型,该模型能够根据给定的静态图像和音乐直接生成舞蹈…

免费 OSS 资源 Backblaze B2 使用最新指南

免费的对象存储资源日渐枯竭,Backblaze 是为数不多仍提供免费 OSS 的良心厂商。另外一个则是大名鼎鼎的 Cloudflare R2。虽然免费,但 Backblaze 也修改了政策:如果不验证信用卡的话是不能打开 Public 选项的,或者支付一美金。估计…

24.5.26(树链剖分板子,二分+线段树)

星期一: 补重庆科技 C 二分 牛客传送门 思路:二维前缀和表示到第 i个人第 j个弹巢开了多少发,和st【i】表示第 i个人开的是第几个弹巢 对于 l和r的查询,使用前缀和二分找出第一个…

【UE5.1 角色练习】06-角色发射火球-part1

前言 在上一篇(【UE5.1 角色练习】05-火球发射物-CSDN博客)基础上实现角色可以发射火球的技能 效果 步骤 一、准备 1. 打开角色蓝图,添加两个浮点型变量,分别表示当前的MP值和满状态的MP值 添加一个函数,这里命名…

解密 Alpha 勒索软件

Alpha 勒索软件很容易与 ALPHV 勒索软件混淆,但其实这是两个不同的勒索软件团伙。近期,Alpha 勒索软件团伙在暗网上建立了数据披露网站,并且对外公开了6个受害者。 通常来说,勒索软件运营者在启动数据披露网站前会保持攻击态势。一…

c++ 实现 梯度下降线性回归模型

理论与python实现部分 3.1. 线性回归 — 动手学深度学习 2.0.0 documentation c代码 没能力实现反向传播求梯度&#xff0c;只能自己手动算导数了 #include <bits/stdc.h> #include <time.h> using namespace std;//y_hat X * W b // linreg 函数&#xff1a…

无经验求职者的福音:AI生成简历的便捷之道

第一步你需要先给自己写个简历&#xff0c;简历就是你求职时的一张脸&#xff0c;“漂亮”程度与否那可大了去了。一份漂亮的简历不仅内容满满当当突出重点&#xff0c;而且排版清晰亮眼&#xff0c;能让hr一下子捕捉到重点。 来看看一份漂亮的简历长啥样↓ 工作经历、个人能力…

Go语言

Go语言 Go语言全称Golanguage&#xff0c;Go&#xff08;又称 Golang&#xff09;是 Google 的 Robert Griesemer&#xff0c;Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译并发型语言。于2009年首次发布 官网 特点 简单易学&#xff1a;Go语言语法简洁明了&#x…

【C++】Vector的简易模拟与探索

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

04Django项目基本运行逻辑及模板资源套用

对应视频链接点击直达 Django项目用户管理及模板资源 对应视频链接点击直达1.基本运行逻辑Django的基本运行路线&#xff1a;视图views.py中的 纯操作、数据返回、页面渲染 2.模版套用1.寻找一个好的模版2.模板部署--修改适配联动 OVER&#xff0c;不会有人不会吧不会的加Q1394…

Java 类加载过程和双亲委派模型

Java 类加载过程概述 在 Java 中&#xff0c;类装载器把一个类装入 Java 虚拟机中&#xff0c;要经过三个步骤来完成&#xff1a;装载、链接和初始化&#xff0c;其中链接又可以分成校验、准备、解析 Java类加载过程分为如下步骤&#xff1a; 1.装载&#xff08; 加载&#xf…

Python编程-后端开发之Django5应用请求处理与模板基础

Python编程-后端开发之Django5应用请求处理与模板基础 最近写项目&#xff0c;刚好用到了Django&#xff0c;现在差不多闲下来&#xff0c;个人觉得单体项目来讲django确实舒服&#xff0c;故写此总结 模板语法了解即可&#xff0c;用到了再看&#xff0c;毕竟分离已经是主流操…

LeetCode300:最长递增子序列

题目描述 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的 子序列 代码…

react 函数组件 开发模式默认被渲染两次

这是 React 刻意为之&#xff0c;函数式组件应当遵从函数式编程风格&#xff0c;每次执行应该是无副作用的(no sideEffect)&#xff0c;在 dev 下多次渲染组件&#xff0c;是为了防止开发者写出有问题的代码。 用 React 写函数组件&#xff0c;如何避免重复渲染&#xff1f; -…

Java学习【面向对象综合练习——实现图书管理系统】

Java学习【面向对象综合练习——实现图书管理系统】 前期效果图书的创建用户的创建操作的实现完善操作显示图书查找图书新增图书借阅图书归还图书删除图书 前期效果 用户分为普通用户和管理员&#xff0c;登录进系统之后可以对图书进行一系列操作&#xff0c;此时我们要明白&am…

斐讯N1刷OpenWRT并安装内网穿透服务实现远程管理旁路由

文章目录 前言1. 制作刷机固件U盘1.1 制作刷机U盘需要准备以下软件&#xff1a;1.2 制作步骤 2. N1盒子降级与U盘启动2.1 N1盒子降级2.2 N1盒子U盘启动设置2.3 使用U盘刷入OpenWRT2.4 OpenWRT后台IP地址修改2.5 设置旁路由&无线上网 3. 安装cpolar内网穿透3.1 下载公钥3.2 …

时空数据治理白皮书(2024)

来源&#xff1a;泰伯智库&#xff1a; 近期历史回顾&#xff1a;

企业微信修改主体花了大几千的踩坑经验,家人们避雷

企业微信变更主体有什么作用&#xff1f;如果原有的公司注销了&#xff0c;或者要更换一家公司主体来运营企业微信&#xff0c;那么就可以进行变更主体&#xff0c;变更主体后才可以保留原来企业微信上的所有用户&#xff0c;否则就只能重新申请重新积累用户了。企业微信变更主…