早睡早起,方能养生
Sleep early rise early, way to keep healthy

国外支付Stripe PHP

super
2020-11-04 18:37
views 6940

Stripe支付 :

 

注册账户:https://dashboard.stripe.com/register

 

支付类型: 预设结账页面 (Prebuilt Checkout page)

 

简介:跳转到stripe结算页面进行支付

 

文档:

https://stripe.com/docs/payments/accept-a-payment

 

示例图片:

 

checkout-preview.png

 

跳转到Stripe的付款页面结算(如上图),Stripe将付款结果发送给我们的服务器(类似微信支付的回调,url需指定)

 

图上的商品信息(图片,文字及价格)提前由API传入,生成session_id,由web页面 js 跳转即可

 

image.png

 

不必理会此处的“产品”,上面的功能用不到这个

 

1)安装Stripe,本节以ThinkPHP5.1为例,PHP7.1

 

composer require stripe/stripe-php

 

2)秘钥

 

获取地址: https://dashboard.stripe.com/test/apikeys

 

Html秘钥是Html页面所使用的秘钥

 

PHP秘钥是PHP Code下单时所使用的秘钥

 

image.png

 

3)PHP代码

 

PHP Code:

 

<?php

namespace app\index\controller;

use Stripe\Stripe;
use think\Db;

class Pay extends Common
{
    private static $key;
    
    public function initialize()
    {
        parent::initialize();
        self::$key = 'sk_test_51HjJtrB1etHLMjYqENRyuj83dztQqbom5T1apAK5OXXXXXXXXX (你的PHP密钥) XXXXXXXXXXXXXXX1pVmlTxAbaPEigL00goDSLuUm';
    }

    /**
     * Stripe支付
     * @access private
     * @author super
     * @date 2020-11-04
     * @param array $product 商品信息
     * @param int|float $amount 支付金额
     * @param array $pay_type 支付类型
     * @param string $currency 货币类型 小写
     * @return array
     */
    private static function stripePay($product, $amount, $pay_type = ['card'], $currency = 'aud')
    {
        require __DIR__ . '/../../../vendor/autoload.php';

        \Stripe\Stripe::setApiKey(self::$key);

        header('Content-Type: application/json');

        $YOUR_DOMAIN = 'https://rongsp.com';

        $checkout_session = \Stripe\Checkout\Session::create([
            'payment_method_types' => $pay_type,
            'line_items' => [[
                'price_data' => [
                    'currency' => $currency,
                    'unit_amount' => $amount,
                    'product_data' => $product
                ],
                'quantity' => 1,
            ]],
            'mode' => 'payment',
            'success_url' => $YOUR_DOMAIN . '/success.html', // 支付成功后跳转url
            'cancel_url' => $YOUR_DOMAIN . '/cancel.html', // 支付失败后跳转url
        ]);
        return ['id' => $checkout_session->id, 'payment_intent' => $checkout_session->payment_intent]; // payment_intent是识别支付与通知关系的唯一凭证
    }
    
    public function pay()
    {
        // 订单ID
        $order_id = input('order_id');
        
        // 查询订单详情
        $order_info = Db::name('orders')->where('order_id', $order_id)->find();

        $product = [
            'name' => 'Order Number:' . $order_info['order_sn'] ,
            'images' => [
                'https://rongsp.com/Super/favicon.ico'
            ]
        ];
        $amount = $order_info['price'] * 100;

        $result = self::stripePay($product, $amount);
        if (!isset($result['id']) || !isset($result['payment_intent'])) {
            returnData(500, 'ERROR! BUSY NETWORK!');
        }


		// 将凭证保存,便于在回调时查询订单
        $update = Db::name('orders')->where('order_id', $order_info['order_id'])->update(['payment_intent' => $result['payment_intent']]);
        if (!$update) {
            returnData(500, 'ERROR! BUSY NETWORK!');
        }

        returnData(200, 'SUCCESS!', ['id' => $result['id']]);
    }

    // 支付成功通知
    public function successNotify()
    {
        // Set your secret key. Remember to switch to your live secret key in production!
        // See your keys here: https://dashboard.stripe.com/account/apikeys
        \Stripe\Stripe::setApiKey(self::$key);

        $payload = @file_get_contents('php://input');
        $event = null;
        
        try {
            $event = \Stripe\Event::constructFrom(
                json_decode($payload, true)
            );
        } catch(\UnexpectedValueException $e) {
            // Invalid payload
            http_response_code(400);
            exit();
        }

        // Handle the event
        switch ($event->type) {
            case 'charge.succeeded':
                
                $succeeded = $event->data->object;
                
                if ($succeeded->status == 'succeeded'){

                    $payment_intent = $succeeded->payment_intent;

                    // 查询订单详情
                    $order_info = Db::name('orders')->where('payment_intent', $payment_intent)->find();
                    if (!$order_info) {
                        http_response_code(200);exit;
                    }

                    if ($order_info['status'] != 0) {
                        return;
                    }

                    // 订单标记为处理中
                    Db::name('orders')->where('order_id', $order_info['order_id'])->update(['pay_time' => time(), 'status' => 3]);

                    // 订单处理
                    // ...

                    // 标记为处理完成
                    Db::name('orders')->where('order_id', $order_info['order_id'])->update(['status' => 1]);
                }
                break;
            default:
                echo 'Received unknown event type ' . $event->type;
        }
        http_response_code(200);
    }
}

 

web 代码:

 

<html>
  <head>
    <title>Buy test</title>
    <script src="https://js.stripe.com/v3/"></script>
  </head>
  <body>
    <button id="checkout-button">Checkout</button>

    <script type="text/javascript">
      // Create an instance of the Stripe object with your publishable API key
      var stripe = Stripe('pk_test_51HjJtrB1etHLMjYqPgu55dKoPIDnmh2H8Z96TiXXXXXXXXXX( 这里填上你的Html密钥 )XXXXXXXXXXXXXzvuKWr70xq8c0kNpVzD6r00g3oSMoE5');
      var checkoutButton = document.getElementById('checkout-button');

      checkoutButton.addEventListener('click', function() {
        // Create a new Checkout Session using the server-side endpoint you
        // created in step 3.
        fetch('/api.php/Pay/pay/order_id/1', {
          method: 'POST',
        })
        .then(function(response) {
          return response.json();
        })
        .then(function(session) {
            
            console.log(session)
            
          return stripe.redirectToCheckout({ sessionId: session.id });
        })
        .then(function(result) {
          // If `redirectToCheckout` fails due to a browser or network
          // error, you should display the localized error message to your
          // customer using `error.message`.
          if (result.error) {
            alert(result.error.message);
          }
        })
        .catch(function(error) {
          console.error('Error:', error);
        });
      });
    </script>
    
  </body>
</html>

 

4)测试

 

页面:

 

image.png

 

点击 Checkout 后跳转到

 

image.png

 

5)接收支付结果通知

 

image.png

 

点击右上角“添加端点”(已经添加了一个)

 

添加一个可在外部访问(不需要Token或Session等凭证)的URL,事件选择charge.succeeded(支付成功通知)

 

image.png

 

支付通知相关代码见上方 PHP 代码

 

(以上是由)stripe提供的测试环境进行记录(调试模式可任意付款,便于测试)

 

如果使用了测试环境(密钥),记得上线要切换正式环境的 Html 及 PHP秘钥

 

---禁止转载---



分享
24 条讨论
top