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.rhkb.cn/news/332926.html

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

相关文章

Jenkins pipeline发布前端项目

说明:第一次使用jenkins生成pipeline片段,做个记录... 1.全局工具配置添加自定义node版本 2.系统管理添加前端应用部署服务器 2.1 点击高级选择账号密码验证方式,添加服务器的用户和密码 3.系统管理--凭据--系统--全局凭据--添加自己的git凭据…

网站笔记:huggingface model memory calculator

Model Memory Utility - a Hugging Face Space by hf-accelerate 这个工具可以计算在 Hugging Face Hub上托管的大型模型训练和执行推理时所需的vRAM内存量。模型所需的最低推荐vRAM内存量表示为“最大层”的大小,模型的训练大约是其大小的4倍(针对Adam…

PL5358A 单芯锂离子/聚合物电池保护IC芯片

一般说明 PL5358A系列产品是锂离子/聚合物电池保护的高集成解决方案。PL5358A包含先进 的功率MOSFET,高精度电压检测电路和延迟电路。5358A被放入一个超小的SOT23-5封装,只有一个外部元件,使其成为理想的解决方案,在有限的…

NDIS协议驱动(一)

Microsoft Windows 操作系统使用基于 1978 年国际标准化组织 (ISO) 开发的七层网络模型的网络体系结构。 ISO 开放系统互连 (OSI) 参考模型将网络描述为“一系列协议层,具有分配给每个层的一组特定函数。 每个层都向更高层提供特定的服务,同时阻止这些层…

中国区 AWS 控制台集成 ADFS 登录

前言 本文将使用一台 Windows Server 2019 服务器实现自建 AD ADFS 环境集成到中国区 AWS 控制台进行单点登录. 参考文档: https://aws.amazon.com/cn/blogs/china/adfs-bjs/ 配置 AD 生产环境建议先给本地连接设置静态 IP 地址, 不设置也没事儿, 后面配置功能的时候会有 W…

设计模式11——代理模式

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

git工作流程

以财务开发为例子: 1. 新建分支 1.1. upstream新建分支:finance-feature 1.2. origin新建对应分支:finance-feature 1.3 新建本地分支 git branch finance-feature 注: 同步远程分支:git fetch upstream feature…

【设计模式】JAVA Design Patterns——Command(事务模式)

🔍目的 将请求封装为对象,从而使你可以将具有不同请求的客户端参数化,队列或记录请求,并且支持可撤销操作。 🔍解释 真实世界例子 有一个巫师在地精上施放咒语。咒语在地精上一一执行。第一个咒语使地精缩小&#xff0…

群晖NAS安装web服务器和搭建PHP环境

文章目录 安装Web Station 和 PHP配置PHP配置新站点(虚拟主机):配置nginx 安装MariaDB修改数据库配置配置远程连接远程连接 最近折腾了一台群晖NAS,并搭建了一套web服务器,关于其中的一些设置,和传统的Linu…

力扣HOT100 - 31. 下一个排列

解题思路: 数字是逐步增大的 步骤如下: class Solution {public void nextPermutation(int[] nums) {int i nums.length - 2;while (i > 0 && nums[i] > nums[i 1]) i--;if (i > 0) {int j nums.length - 1;while (j > 0 &&…

基于51单片机多功能太阳能充电器设计

1 绪论1.1 本课题研究背景及现状 当代社会随着一些不可再生资源如煤炭,石油等日益减少,使得各国社会经济越来越受能源问题的约制,因此许多国家开始逐渐的实行“阳光计划”,开发洁净的能源如太阳能,用以成为本国经济发…

javaEE—图书管理系统(基础代码版)

前言: 本篇博客是集合了javaEE所学的知识构建的一个基础框架,讲述着面向对象的过程是如何做到多对象交互协作完成框架的构建的。利用了数组,接口,类和对象,抽象类,Object类等知识来完成。 后续会加入数据…

BGP选路实验

编写实验报告: 1、拓扑信息 2、要求及分析 3、配置命令 4、测试 1、拓扑信息 2、要求及分析 1、使用preval策略,确保R4通过R2到达192.168.10.0/24 2、使用AS Path策略,确保R4通过R3到达192.168.11.0/24 3、配置MED策略,确保R4…

嵌入式UI开发-lvgl+wsl2+vscode系列:1、资料收集以及Windows下WSL2模拟环境运行示例demo

文章目录 一、前言二、资料收集三、Windows下WSL2上编译运行lvgl的demo程序1、lvgl简介2、lvgl特性3、配置要求4、Windows下vscodewsl2模拟环境搭建4.1、安装vscodewsl24.2、下载获取项目:4.3、安装显卡驱动4.4、下载lvgl并编译运行示例demo 四、最后 一、前言 UI界…

leetcode437 路径总和III-哈希表+前缀和

题目 给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。 路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节…

专为汽车内容打造的智能剪辑解决方案

汽车内容创作已成为越来越多车主和汽车爱好者热衷的活动。然而,如何高效、便捷地将行车途中的精彩瞬间转化为高质量的视频作品,一直是困扰着广大用户的一大难题。美摄科技凭借其深厚的视频处理技术和智能分析能力,推出了专为汽车内容记录而生…

探索python循环逻辑的魅力:从无限到有限

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、引言:循环逻辑的初步认识 二、无限循环:持续运转的引擎 三、有…

JavaWeb-JS

目录 学习重点 什么是 JavaScript? Web标准 JS的引入方式 JS的基本语法 JS的函数 JS的对象 JS事件监听 学习重点 js 引入方式 js 基础语法 js 函数 js 对象 js 事件监听 什么是 JavaScript? Web标准 Web 标准也称为网页标准 ,由一系列的标准组成&#xff0…

安泰电子:功率放大器的选择方法有哪些

选择适合的功率放大器是实现电子系统中的关键步骤之一。以下是一些选择功率放大器的常用方法和考虑因素: 功率需求:首先确定你的系统需要多大的功率输出。功率输出需求通常由被驱动设备的功率要求决定。计算出所需功率后,选择一个具有适当功率…

Java数组详解

Java数组详解 📚 Java数组详解:一篇文章搞懂Java中的数组知识摘要引言1. 数组的定义与创建📦1.1 数组的定义1.2 数组的创建及初始化数组不进行初始化时的默认值 2. 数组的遍历🔍2.1 使用for循环2.2 使用增强for循环2.3 使用Arrays…