hatemgodaphp/laravel-google-merchant-api

Laravel Google Merchant Products API for Google Shopping.

1.0.0 2024-04-16 21:48 UTC

This package is auto-updated.

Last update: 2024-09-16 23:02:31 UTC


README

一个用于管理 Google Shopping 中 Google Merchant Center 报文的甜蜜包。此包准备实现为商家提供的先进 内容 API

示例用法

use MOIREI\GoogleMerchantApi\Facades\ProductApi;
use MOIREI\GoogleMerchantApi\Facades\OrderApi;

...

ProductApi::insert(function($product){
    $product->offerId(1)
        	->title('Purple Shoes')
        	->description('What are thooose!!')
        	->price(10)
        	->custom('purchase_quantity_limit', 1000)
            ->availabilityDate( today()->addDays(7) );
})->then(function($response){
    echo 'Product inserted';
})->otherwise(function($response){
    echo 'Insert failed';
})->catch(function($e){
    echo($e->getResponse()->getBody()->getContents());
});

OrderApi::list()->then(function($response){
    //
})->otherwise(function($response){
    echo 'List failed';
})->catch(function($e){
    echo($e->getResponse()->getBody()->getContents());
});


OrderApi::scout(); // Scout and fire event

特性

  • 产品 API
    • 实现 insertgetdeletelist API 调用
    • 使用定义的 schema 接口直接与 eloquent 模型(如产品模型)一起工作
    • 事件监听器以响应对 eloquent 模型所做的更改,并自动将它们 insert
  • 订单 API
    • 实现 acknowledgecancelcancelLineItemrejectReturnLineItemreturnRefundLineItemgetlist API 调用。
    • 内部调度器扫描未确认的订单并触发事件。这意味着您在 Google Shopping 上的新订单可以自动确认和注册。
    • 包括用于 testOrders 的沙盒功能。
  • 多个商家(1.1.0)

更新到 1.1.x

尽管向后兼容,但请确保更新您的配置以使用多个商家。

安装

通过 composer

composer require moirei/laravel-google-merchant-api

安装服务提供者(对于 Laravel>=5.5 跳过);

// config/app.php
'providers' => [
    ...
    MOIREI\GoogleMerchantApi\GoogleMerchantApiServiceProvider::class,
],

发布配置

php artisan vendor:publish --tag="google-merchant-api-config"

设置 & 授权

  • 按照此处的说明进行操作并创建服务帐户密钥。在应用程序根目录中创建 storage/app/google-merchant-api/service-account-credentials.json 并存储下载的 json 内容
  • 获取您的数字商家 ID
  • 将您的商家 ID 和服务帐户凭据的路径添加到配置中
  • 在配置中设置产品内容中的属性部分,如果您需要使用数组或模型

用法

多个商家

1.1.0 开始,我们可以现在定义多个商家,并通过从订单或产品 API 类中调用 merchant 方法在它们之间切换。

ProductApi::merchant('my-pet-store')->insert($product);
// config/laravel-google-merchant-api.php
...
    'merchants' => [
        'my-pet-store' => [
			'app_name' => config('app.name'),
			'merchant_id' => '000000000',
			'client_credentials_path' => storage_path('app/my-pet-store-credentials.json'),
		]
    ],
...

或者

ProductApi::merchant([
    'app_name' => 'My Pet Store',
    'merchant_id' => '000000000',
    'client_credentials_path' => storage_path('app/my-pet-store-credentials.json')
])->insert($product);

产品 API

可以通过 insertgetdeletelist 方法查询 Google Merchant 内容。产品内容包含并通过对 Product 类进行操作来处理。可以直接传递此类的实例或通过闭包回调解析实例。可以通过以下方式填充实例:

  • 直接访问底层属性。请参阅 特殊函数
  • 传递一个 eloquent 模型,或者通过
  • 传递一个原始数组

要传递一个数组或模型,必须在配置中定义属性关系。

插入

插入方法创建一个新的内容,如果 channelcontentLanguagetargetCountryofferId 相同,则还更新旧内容。

$attributes = [
    'id' => 1, // maps to offerId (if set in config)
    'name' => 'Product 1', // likewise maps to title
];
ProductApi::insert(function($product) use($attributes){
    $product->with($attributes)
        	->link('https://moirei.com/mg001')
        	->price(60, 'USD');
})->then(function($data){
    echo 'Product inserted';
})->otherwise(function(){
    echo 'Insert failed';
})->catch(function($e){
    dump($e);
});

使用数组:

use MOIREI\GoogleMerchantApi\Contents\Product\Product as GMProduct;

...
$attributes = [
    'id' => 1,
    'name' => 'Product 1',
];
$product = (new GMProduct)->with($attributes);

必须根据配置中的属性映射定义 attributes 值。

使用 Eloquent 模型:

use App\Models\Product;
use MOIREI\GoogleMerchantApi\Contents\Product\Product as GMProduct;


...
$model = Product::find(1);
$product = (new GMProduct)->with($model);

ProductApi::insert($product)->catch(function($e){
    // always catch exceptions
});

必须根据配置中的属性映射定义模型 attributes 值。要访问未定义的模型属性,请使用访问器和自定义模型属性

protected $appends = [
    'availability',
    'gm_price',
];

...

public function getAvailabilityAttribute(){
    return 'in stock'; // calculate
}
public function getGmPriceAttribute(){
    return [
        'value' => $this->price,
        'currency' => $this->currency->code,
    ];
}

对于设置自定义产品内容(customAttributes),您可能最好使用 custom() 方法。同样,对于 availabilityDate,请使用 availabilityUntil() 方法。

使用事件 & 监听器:

提供的事件和监听器可以设置为当您的应用程序创建或更新模型时,自动插入产品内容。

要设置此功能,请将以下代码片段添加到您的eloquent模式中。变量product可以是模型或数组。

use MOIREI\GoogleMerchantApi\Events\ProductCreatedOrUpdatedEvent;

...

/**
 * The "booting" method of the model.
 *
 * @return void
 */
protected static function boot() {
    parent::boot();

    // when a product is created
    static::created(function(Product $product){
        // perhaps a logic to ignore drafts and private products
        if($product->is_active && (config('app.env') === 'production')){
        	event(new ProductCreatedOrUpdatedEvent($product));
        }
    });

    // when a product is updated
    static::updated(function(Product $product){
        // perhaps a logic to ignore drafts and private products
        if($product->is_active && (config('app.env') === 'production')){
        	event(new ProductCreatedOrUpdatedEvent(function($gm_product) use ($product){
                $gm_product->with($product)
                    	   ->preorder()
                    	   ->availabilityDate($product->preorder_date);
            }));
        }
    });
}

接下来,在EventServiceProvider.php中定义事件关系。

use MOIREI\GoogleMerchantApi\Listeners\ProductCreatedOrUpdatedListener;

...

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    ...,
    /**
     * Product events
     */
    ProductCreatedOrUpdatedEvent::class => [
        ProductCreatedOrUpdatedListener::class,
    ],

];

获取 & 列表

ProductApi::get($product)->then(function($data){
    //
})->catch(function($e){
    // always catch exceptions
});

list方法调用get方法,不传递任何参数;

ProductApi::list()->then(function($data){
    //
});

因此,以下代码也应该可以检索产品列表

ProductApi::get()->then(function($data){
    //
});

删除

ProductApi::delete($product)->then(function($data){
    //
});

要使用事件监听器进行设置,请将以下代码添加到您的eloquent模型中

use MOIREI\GoogleMerchantApi\Events\ProductDeletedEvent;

...

protected static function boot() {
    parent::boot();

    ...

    // when a product is deleted
    static::deleted(function(Product $product){
        if(config('app.env') === 'production'){
        	event(new ProductDeletedEvent($product));
        }
    });
}

然后在EventServiceProvider.php中定义关系

use MOIREI\GoogleMerchantApi\Listeners\ProductDeletedListener;

...

protected $listen = [
    ...,
    ProductDeletedEvent::class => [
        ProductDeletedListener::class,
    ],
];

订单API

请注意,这些实现尚未经过充分测试。

使用API方法

acknowledgecancelcancelLineItemrejectReturnLineItemreturnRefundLineItemgetlist方法目前实现了与您的Google Merchant交互。

使用这些方法的格式在整个包中都是标准的。例如,可以通过以下方式确认订单:

OrderApi::acknowledge(function($order){
    $order->id('TEST-1953-43-0514');
});

或通过

$order = (new Order)->with([
    'id' => 'TEST-1953-43-0514',
]);
OrderApi::acknowledge($order);

此外,还提供了listAcknowledged方法,以便在需要时列出已确认的订单。

计划侦察兵

如果配置中的schedule_orders_check设置为true,则包将定期侦察未确认的订单,并触发一个\MOIREI\GoogleMerchantApi\Events\NewOrdersScoutedEvent事件。此事件包含一个包含订单的array,订单类为\MOIREI\GoogleMerchantApi\Contents\Order。订单结构遵循订单资源

监听器中的示例处理

use MOIREI\GoogleMerchantApi\Events\NewOrdersScoutedEvent;
use MOIREI\GoogleMerchantApi\Facades\OrderApi;

...
public function handle(NewOrdersScoutedEvent $event)
{
    $merchant = $event->merchant; // array key as defined in config
    $merchant_id = $event->merchant_id;

    foreach($event->orders as $gm_order){
        OrderApi::acknowledge($gm_order);

        $gm_order = $gm_order->all(); // get all attributes, including mutated attributes
        foreach($gm_order['lineItems'] as $line_item){
            $model = $line_item['model']; // retrieves model
            $quantity = $line_item['quantityOrdered'];
            $shipping = $line_item['shippingDetails'];
            $delivery_date = $shipping['deliverByDate']->diffForHumans();

            // register new order item
        }

        // register new order
    }
}

备注:

  • 访问lineItems将自动解析并附加相应的模型到每个项目。当然,这假设您插入的产品offerId与模型的ID & 主键相匹配。
  • 如果您尚未启动Laravel计划程序,您需要将以下Cron条目添加到您的服务器。 * * * * * php artisan schedule:run >> /dev/null 2>&1
  • 确保计划程序设置正确非常重要。为此,提供了MOIREI\GoogleMerchantApi\Events\OrderContentScoutedEvent事件。如果配置中的debug_scout设置为true,则每当计划程序触发时,都会触发此事件。

沙盒

OrderApi类提供了一种调用某些沙盒操作的方式。例如:

OrderApi::sandbox()->create(function($order){
    $order->shippingCost(30)
          ->shippingOption('economy')
          ->predefinedEmail('pog.dwight.schrute@gmail.com')
          ->predefinedDeliveryAddress('dwight');
})

您可以使用

OrderApi::sandbox()->testCreate();

来使用预设示例。

实现沙盒操作

命令

此包提供了一个用于侦察订单的Artisan命令。

php artisan gm-orders:scout

处理错误

抛出异常的方法

  • MOIREI\GoogleMerchantApi\Contents\Product::with()

    如果提供的属性不是模型或数组,则抛出MOIREI\GoogleMerchantApi\Exceptions\ProductContentAttributesUndefined

  • API类中的insertgetdeletelistlistAcknowledgedscout方法如果客户端请求损坏、失败、未定义或未授权,将抛出GuzzleHttp\Exception\ClientException

  • 如果传递了一个无法解析的实体作为内容属性,则抛出MOIREI\GoogleMerchantApi\Exceptions\Invalid**Input异常。

  • 如果无法解析商人ID或凭证路径,则merchant方法抛出MOIREI\GoogleMerchantApi\Exceptions\InvalidMechantDetails

应使用catch函数处理异常。如果进行同步调用,请使用try-catch块。鉴于Google有千万个理由拒绝任何请求,因此建议始终捕获请求(并通知业务逻辑)。

设计说明

  • 如果使用默认的异步功能,则插入、列表、获取、删除方法始终返回原始实例的克隆。这允许多个请求的then、otherwise和catch回调不会相互覆盖。如果设置为同步模式,这些方法返回Guzzle响应。
  • 如果调用删除方法且解析的内容ID无效,则它将不会发出任何请求或抛出任何错误。如果调用get方法,则返回产品或订单列表。
  • 有效的产品内容ID遵循以下模式:online:en:AU:1,即 channel:contentLanguage:targetCountry:offerId。当然,此ID是自动生成的;除了 offerId 外,其他属性有默认值。
  • 请求可能需要最多2小时才能在您的Google Merchant Center上反映出来。请耐心等待!
  • 与ProductApi或OrderApi类不同,events构造函数可以接受Model、数组或回调。
  • ProductOrder或任何内容类上调用all方法将解析所有已更改的属性。例如,$order['lineItems'][0]['shippingDetails']['deliverByDate']返回一个Carbon

同步调用

以上所有操作默认为异步。要执行同步调用,请使用sync方法。

try{
    $response = ProductApi::sync()->insert(function($product){
        $product->offerId(1)
            	->country('AU')
            	->inStock(false);
    });
}catch(\GuzzleHttp\Exception\ClientException $e){
    //
}

注意:在这种情况下,如insertgetdeletelist等方法在异步调用时返回Guzzle响应(而不是ProductApiOrderApi的实例。这意味着您的异常块应围绕请求进行包裹。

贡献

此包旨在为Google Merchant的Google购物API提供Laravel解决方案。目前,只有产品内容得到了充分的实施和测试。对于订单、退款等,欢迎提出想法和pull-requests。

致谢

许可证

MIT许可证(MIT)。有关更多信息,请参阅许可证文件