承接 cgunnels/lunarphp-stripe 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

cgunnels/lunarphp-stripe

Composer 安装命令:

composer create-project cgunnels/lunarphp-stripe

包简介

Stripe payment driver for Lunar.

README 文档

README

This addon enables Stripe payments on your Lunar storefront.

Alpha Release

This addon is currently in Alpha, whilst every step is taken to ensure this is working as intended, it will not be considered out of Alpha until more tests have been added and proved.

Tests required:

  • Successful charge response from Stripe.
  • Unsuccessful charge response from Stripe.
  • Test manual config reacts appropriately.
  • Test automatic config reacts appropriately.
  • Ensure transactions are stored correctly in the database
  • Ensure that the payment intent is not duplicated when using the same Cart
  • Ensure appropriate responses are returned based on Stripe's responses.
  • Test refunds and partial refunds create the expected transactions
  • Make sure we can manually release a payment or part payment and handle the different responses.

Minimum Requirements

  • Lunar 1.x
  • A Stripe account with secret and public keys

Optional Requirements

  • Laravel Livewire (if using frontend components)
  • Alpinejs (if using frontend components)
  • Javascript framework

Installation

Require the composer package

composer require lunarphp/stripe

Publish the configuration

This will publish the configuration under config/lunar/stripe.php.

php artisan vendor:publish --tag=lunar.stripe.config

Publish the views (optional)

Lunar Stripe comes with some helper components for you to use on your checkout, if you intend to edit the views they provide, you can publish them.

php artisan vendor:publish --tag=lunar.stripe.components

Enable the driver

Set the driver in config/lunar/payments.php

<?php

return [
    // ...
    'types' => [
        'card' => [
            // ...
            'driver' => 'stripe',
        ],
    ],
];

Add your Stripe credentials

Make sure you have the Stripe credentials set in config/services.php

'stripe' => [
    'key' => env('STRIPE_SECRET'),
    'public_key' => env('STRIPE_PK'),
    'webhooks' => [
        'lunar' => env('LUNAR_STRIPE_WEBHOOK_SECRET'),
    ],
],

Keys can be found in your Stripe account https://dashboard.stripe.com/apikeys

Configuration

Below is a list of the available configuration options this package uses in config/lunar/stripe.php

Key Default Description
policy automatic Determines the policy for taking payments and whether you wish to capture the payment manually later or take payment straight away. Available options manual or automatic
sync_addresses true When enabled, the Stripe addon will attempt to sync the billing and shipping addresses which have been stored against the payment intent on Stripe.

Backend Usage

Create a PaymentIntent

use \Lunar\Stripe\Facades\Stripe;

Stripe::createIntent(\Lunar\Models\Cart $cart, $options = []);

This method will create a Stripe PaymentIntent from a Cart and add the resulting ID to the meta for retrieval later. If a PaymentIntent already exists for a cart this will fetch it from Stripe and return that instead to avoid duplicate PaymentIntents being created.

You can pass any additional parameters you need, by default the following are sent:

[
    'amount' => 1099,
    'currency' => 'GBP',
    'automatic_payment_methods' => ['enabled' => true],
    'capture_method' => config('lunar.stripe.policy', 'automatic'),
    // If a shipping address exists on a cart
    // $shipping = $cart->shippingAddress
    'shipping' => [
        'name' => "{$shipping->first_name} {$shipping->last_name}",
        'phone' => $shipping->contact_phone,
        'address' => [
            'city' => $shipping->city,
            'country' => $shipping->country->iso2,
            'line1' => $shipping->line_one,
            'line2' => $shipping->line_two,
            'postal_code' => $shipping->postcode,
            'state' => $shipping->state,
        ],
    ]
]
$paymentIntentId = $cart->meta['payment_intent']; // The resulting ID from the method above.
$cart->meta->payment_intent;

Fetch an existing PaymentIntent

use \Lunar\Stripe\Facades\Stripe;

Stripe::fetchIntent($paymentIntentId);

Syncing an existing intent

If a payment intent has been created and there are changes to the cart, you will want to update the intent so it has the correct totals.

use \Lunar\Stripe\Facades\Stripe;

Stripe::syncIntent(\Lunar\Models\Cart $cart);

Update an existing intent

For when you want to update certain properties on the PaymentIntent, without needing to recalculate the cart.

See https://docs.stripe.com/api/payment_intents/update

use \Lunar\Stripe\Facades\Stripe;

Stripe::updateIntent(\Lunar\Models\Cart $cart, [
    'shipping' => [/*..*/]
]);

Cancel an existing intent

If you need to cancel a PaymentIntent, you can do so. You will need to provide a valid reason, those of which can be found in the Stripe docs: https://docs.stripe.com/api/payment_intents/cancel.

Lunar Stripe includes a PHP Enum to make this easier for you:

use Lunar\Stripe\Enums\CancellationReason;

CancellationReason::ABANDONED;
CancellationReason::DUPLICATE;
CancellationReason::REQUESTED_BY_CUSTOMER;
CancellationReason::FRAUDULENT;
use Lunar\Stripe\Facades\Stripe;
use Lunar\Stripe\Enums\CancellationReason;

Stripe::cancelIntent(\Lunar\Models\Cart $cart, CancellationReason $reason);

Update the address on Stripe

So you don't have to manually specify all the shipping address fields you can use the helper function to do it for you.

use \Lunar\Stripe\Facades\Stripe;

Stripe::updateShippingAddress(\Lunar\Models\Cart $cart);

Charges

Retrieve a specific charge

use \Lunar\Stripe\Facades\Stripe;

Stripe::getCharge(string $chargeId);

Get all charges for a payment intent

use \Lunar\Stripe\Facades\Stripe;

Stripe::getCharges(string $paymentIntentId);

Webhooks

The add-on provides an optional webhook you may add to Stripe. You can read the guide on how to do this on the Stripe website https://stripe.com/docs/webhooks/quickstart.

The events you should listen to are payment_intent.payment_failed, payment_intent.succeeded.

The path to the webhook will be http:://yoursite.com/stripe/webhook.

You can customise the path for the webhook in config/lunar/stripe.php.

You will also need to add the webhook signing secret to the services.php config file:

<?php

return [
    // ...
    'stripe' => [
        // ...
        'webhooks' => [
            'payment_intent' => '...'
        ],
    ],
];

If you do not wish to use the webhook, or would like to manually process an order as well, you are able to do so.

$cart = CartSession::current();

// With a draft order...
$draftOrder = $cart->createOrder();
Payments::driver('stripe')->order($draftOrder)->withData([
    'payment_intent' => $draftOrder->meta['payment_intent'],
])->authorize();

// Using just the cart...
Payments::driver('stripe')->cart($cart)->withData([
    'payment_intent' => $cart->meta['payment_intent'],
])->authorize();

Storefront Examples

First we need to set up the backend API call to fetch or create the intent, this isn't Vue specific but will likely be different if you're using Livewire.

use \Lunar\Stripe\Facades\Stripe;

Route::post('api/payment-intent', function () {
    $cart = CartSession::current();

    $cartData = CartData::from($cart);

    if ($paymentIntent = $cartData->meta['payment_intent'] ?? false) {
        $intent = StripeFacade::fetchIntent($paymentIntent);
    } else {
        $intent = StripeFacade::createIntent($cart);
    }

    if ($intent->amount != $cart->total->value) {
        StripeFacade::syncIntent($cart);
    }
        
    return $intent;
})->middleware('web');

Vuejs

This is just using Stripe's payment elements, for more information check out the Stripe guides

Payment component

<script setup>
const { VITE_STRIPE_PK } = import.meta.env

const stripe = Stripe(VITE_STRIPE_PK)
const stripeElements = ref({})

const buildForm = async () => {
    const { data } = await axios.post("api/payment-intent")

    stripeElements.value = stripe.elements({
        clientSecret: data.client_secret,
    })

    const paymentElement = stripeElements.value.create("payment", {
        layout: "tabs",
        defaultValues: {
            billingDetails: {
                name: `{$billingAddress.value.first_name} {$billingAddress.value?.last_name}`,
                phone: billingAddress.value?.contact_phone,
            },
        },
        fields: {
            billingDetails: "never",
        },
    })

    paymentElement.mount("#payment-element")
}

onMounted(async () => {
    await buildForm()
})

// The address object can be either passed through as props or via a second API call, but it should likely come from the cart.

const submit = async () => {
    try {
        const address = {...}

        const { error } = await stripe.confirmPayment({
            //`Elements` instance that was used to create the Payment Element
            elements: stripeElements.value,
            confirmParams: {
                return_url: 'http://yoursite.com/checkout/complete',
                payment_method_data: {
                    billing_details: {
                        name: `{$address.first_name} {$address.last_name}`,
                        email: address.contact_email,
                        phone: address.contact_phone,
                        address: {
                            city: address.city,
                            country: address.country.iso2,
                            line1: address.line_one,
                            line2: address.line_two,
                            postal_code: address.postcode,
                            state: address.state,
                        },
                    },
                },
            },
        })
    } catch (e) {
    
    }
}
</script>
<template>
    <form @submit.prevent="submit">
        <div id="payment-element">
            <!--Stripe.js injects the Payment Element-->
        </div>
    </form>
</template>

Contributing

Contributions are welcome, if you are thinking of adding a feature, please submit an issue first so we can determine whether it should be included.

Testing

A MockClient class is used to mock responses the Stripe API will return.

cgunnels/lunarphp-stripe 适用场景与选型建议

cgunnels/lunarphp-stripe 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 7 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 03 月 30 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「shop」 「ecommerce」 「cart」 「store」 「stripe」 「headless」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 cgunnels/lunarphp-stripe 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 cgunnels/lunarphp-stripe 我们能提供哪些服务?
定制开发 / 二次开发

基于 cgunnels/lunarphp-stripe 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 7
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 35
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 16
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-03-30