目录
stripe是什么?
环境
配置后台
首先让管理员把你设置成为开发者
然后进入后台
然后你要创建产品,开单周期要写每天,我这里理解成每天都会有人买的
获取产品id
获取密钥,后续代码需要用到
支付代码
唤起支付页面
测试的信用卡号
添加端点webhook
stripe后台配置
非常注意的地方
处理回调代码
golang代码(自己测试用的,go的程序员可以看看)
最后,怎么找到他们的技术支持呢?
stripe是什么?
我们国内有支付宝、微信、银联,国外就有stripe,但是他们是信用卡的。
据我探索,有以下支付方式
- Checkout Session 文档位置:https://docs.stripe.com/api/checkout/sessions
- payment links 文档位置: https://docs.stripe.com/api/payment_links/payment_links
- 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/