Shopify / js-buy-sdk

The JS Buy SDK is a lightweight library that allows you to build ecommerce into any website. It is based on Shopify's API and provides the ability to retrieve products and collections from your shop, add products to a cart, and checkout.
https://shopify.github.io/js-buy-sdk
MIT License
990 stars 262 forks source link

How to create subscription with Recharge App's selling plan? #844

Open awesome-swagger opened 3 years ago

awesome-swagger commented 3 years ago

How can I add selling plan when I checkout?

arobbins commented 3 years ago

I'm working on an integration with ReCharge as well. If anyone has a tutorial / guide to share it would be really helpful!

chris-trapstar commented 3 years ago

Is it possible to integrate with ReCharge API?

explorador commented 3 years ago

ReCharge works based on cart item properties. It stores a discount_variant_id metafield in the product you are offering as a subscription. To add to cart you need to create a request like this:

[
    {
        variantId: storefrontId,
        quantity,
        customAttributes: [
            {
                key: 'subscription_id',
                value: subscription_id,
            },
            {
                key: 'shipping_internal_unit_type',
                value: shipping_interval_unit_type,
            },
            {
                key: 'shipping_interval_frequency',
                value: shipping_interval_frequency,
            },
        ],
    },
]

To get the storefrontId value you have to do this:

// Get storefrontId (from "discount_variant_id" value).
const storefrontId = btoa(
    `gid://shopify/ProductVariant/${discount_variant_id.value}`
)

The rest of the data you should know already how to get it, they are stored in metafields AND from the subscription form

awesome-swagger commented 3 years ago

ReCharge works based on cart item properties. It stores a discount_variant_id metafield in the product you are offering as a subscription. To add to cart you need to create a request like this:

[
  {
      variantId: storefrontId,
      quantity,
      customAttributes: [
          {
              key: 'subscription_id',
              value: subscription_id,
          },
          {
              key: 'shipping_internal_unit_type',
              value: shipping_interval_unit_type,
          },
          {
              key: 'shipping_interval_frequency',
              value: shipping_interval_frequency,
          },
      ],
  },
]

To get the storefrontId value you have to do this:

// Get storefrontId (from "discount_variant_id" value).
const storefrontId = btoa(
  `gid://shopify/ProductVariant/${discount_variant_id.value}`
)

The rest of the data you should know already how to get it, they are stored in metafields AND from the subscription form

Hi @explorador Thanks for your answer

To get the storefrontId value, meant like this?

const enc = new Base64();
const variant = enc.urlEncode(`gid://shopify/ProductVariant/${variantID}`);

And if you guide me how I can get subscription_id, shipping_interval_unit_type, and shipping_interval_frequency, it will be very appreciated. :)

alexSatchell commented 3 years ago

@sagger-dev, @arobbins any luck with this? we are looking to integrate on recharges integrated checkout and are also using the BuySDK. Recharge suggests creating the checkout via the permalink and that is going to break pretty much every process we've defined via the checkout.lineItems functions. I, fortunately, had had no issues mapping selling plans to products, but when I ATC in Shopify they do not display correctly as a subscription... they display like a normal product with the selling plan as a meta field below the image..Any luck with this? Thanks in advance for any support!!

awesome-swagger commented 3 years ago

Still no any luck! I am waiting for @explorador 's answer He can help us, I think :) Thanks

alexSatchell commented 3 years ago

@sagger-dev I can actually help you get those values, they are actually called selling_plan_id, order_interval_unit_type, and order_interval_frequency, in respective order. I'm not sure what platform you are using, but I can help to retrieve them with a JS-based platform. The issue is that I've passed the selling plan id to the checkout via the buySDK and it generates a product with anything in the customAttributes fields just listed as custom fields below the product essentially. We need shopify to recognize those fields and create a subscription item in the checkout as a result, that is what we need @explorador 's help with. But for the immediate, I can aid you in getting those fields.

awesome-swagger commented 3 years ago

Hi @alexSatchell Thank you, I added above values in custom_attributes, but subscription didn't work in checkout page. image

awesome-swagger commented 3 years ago

@alexSatchell Can you please share your experience? 🙏

alexSatchell commented 3 years ago

@sagger-dev so I actually got the same result as you when adding the customAttributes. I am now working to follow the method of creating a cart permalink to preload the cart in the recharge docs. It's unfortunate, because of this we are losing multipass functionality, and the ability to tell if checkout was completed or not. Really hoping with the rollout of selling_plans in Shopify's October API update we will be able to pass selling_plan_id within the native buySDK addLineItem function. Please reach out to me if you come across a solution that allows us to use addLintItems in the future or would like to collab on a call!

arobbins commented 3 years ago

@alexSatchell Did you manage to get the permalink solution working?

I'm finally working on this integration now and am running into this same limitation / confusion.

I've managed to grab the Recharge values selling_plan_id, order_interval_unit_type, and order_interval_frequency by making API requests to the /selling_plan_groups endpoint as outlined here: https://docs.rechargepayments.com/docs/build-a-headless-storefront-with-a-shopify-backend-using-recharge#get-data

But now I'm not sure what to do.

arobbins commented 3 years ago

Hey everyone,

So I finally figured this out. It requires a few steps, but it's working nicely for me.

For 3 years now I've been using the JS SDK to manage the cart in my headless setup (which has worked great). However I haven't been able to add subscription products. I'm guessing this is because the SDK is out of date. The workaround I found today is using the Storefront API directly. Specifically the Cart endpoint: https://shopify.dev/api/storefront/reference/cart/cart#fields-2021-10

Here's how it works:

First, you need to find your selling_plan_id from Recharge. This is the ID that represents a Recharge subscription. I'm finding this value by making a call to the /selling_plan_groups endpoint on the Recharge API https://developer.rechargepayments.com/v1-shopify#list-selling-plan-groups

public function get_products($request) {

    $api_domain = 'https://api.rechargeapps.com';
    $api_endpoint = '/selling_plan_groups';
    $token = 'your_recharge_token_goes_here';

    $response = wp_remote_request($api_domain . '/selling_plan_groups', [
        'headers' => [
            'X-Recharge-Access-Token' => $token
        ]
    ]);

    if (is_wp_error($response)) {
        return $response;
    }

    $body = wp_remote_retrieve_body($response);

    return json_decode($body)->selling_plan_groups;

}

This will return an array of "selling plan groups" which you'll need to loop through to find the selling_plan_id. I should also note that you'll need a Recharge API token before this will work. You can generate one within your Shopify Recharge app.

Once you have the selling_plan_id you'll need to hit the cartCreate mutation on the Storefront API. https://shopify.dev/api/storefront/reference/cart/cartcreate This basically mimics what we're doing using the JS SDK. Here's what my code looks like:

public function graph_query_create_cart() {
      return [
         "query" => 'mutation cartCreateMutation($cartInput: CartInput) {
            cartCreate(input: $cartInput) {
              cart {
                id
                checkoutUrl
                lines(first:10) {
                  edges {
                     node {
                        quantity
                        merchandise {
                          __typename
                          ... on ProductVariant {
                            id
                          }
                        }
                        sellingPlanAllocation {
                          sellingPlan {
                            id
                            name
                          }
                          priceAdjustments {
                            price {
                              amount
                            }
                            compareAtPrice {
                              amount
                            }
                            perDeliveryPrice {
                              amount
                            }
                          }
                        }                       
                     }
                   }
                }
              }
            }
          }',
         "variables" => [
            'cartInput' => [
               "lines" => [
                  [
                     "quantity" => 1,
                     "merchandiseId" => "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC8yMjIyMTk1MDgxMjIwOA==",
                     "sellingPlanId" => "Z2lkOi8vc2hvcGlmeS9TZWxsaW5nUGxhbi80NDc3MDkyMzI="
                  ]
               ]
            ]
         ]
      ];
   }

Shopify has a guide for doing this here: https://shopify.dev/custom-storefronts/products/subscriptions#create-a-cart-and-a-subscription-line-item

Within the query variables I'm passing the selling_plan_id as sellingPlanId. It looks different here compared to what's returned from Recharge because you need to format the value into a Storefront ID.

To do this, take your selling_plan_id and append it to this string: gid://shopify/SellingPlan/. It should look something like this:

gid://shopify/SellingPlan/447709232

Then, base64 encode it... which comes to: Z2lkOi8vc2hvcGlmeS9TZWxsaW5nUGxhbi80NDc3MDkyMzI=

The merchandiseId value is just the Shopify variantId base64 encoded in this format:

gid://shopify/ProductVariant/22221950812208

Once you make the cartCreate mutation you'll receive back a response with a checkoutUrl -- just like the JS SDK.

Boom you're done. This is using Shopify's native checkout page as well which is super cool.

awesome-swagger commented 3 years ago

Hello @arobbins Your reference was very helpful. I appreciate very much for that. Btw I have a last request. To fetch cartLines, I have added sellingPlanAllocation into cart query like this.

sellingPlanAllocation {
  sellingPlan {
    id
    name
  }
  priceAdjustments {
    price {
      amount
    }
    compareAtPrice {
      amount
    }
    perDeliveryPrice {
      amount
    }
  }
}

for the products added subscription, above code worked well. But no-added products, it returns error - "Access denied for sellingPlanAllocation field. Required access: 'unauthenticated_read_selling_plans' access scope."

Can we add condition for the case? Hope to hearing from you Thank you

EricWVGG commented 2 years ago

I'm considering taking on a project that would be built in Gatsby and would require Recharge subscriptions. Could anyone update this thread and let me know if you've created a successful implementation?

sjviome commented 2 years ago

Is there a validity associated with the generated cart URL?

I've observed that once a customer checks out using the link, the cart is deleted.

I'm intending to create a permalink to the cart. Any thoughts?

explorador commented 2 years ago

I have my comments off so I didn't ignore the messages on purpose. You have to use Recharge's API to implement this with the instructions I provided. We were able to do it but the problem you'll have is with API limits. You'll have to rotate keys or you might hit Recharge's limit. Shopify's native subscription is the best option to avoid this. I think Recharge supports this for new customers but we decided we don't want to deal with them anymore. We are actually considering Skio, they said they are gonna helps us move all our Recharge subscriptions to native subscriptions, their customer portal seems much better. We have thousands of subscriptions and Recharge didn't want to give us more API keys plus they said that they can't move all our subscriptions to native cause of Shopify limitations (If you do some research about it, you'll know they are lying). If I were Shopify, I wouldn't be happy about it, they are pretty much blaming them... Skio is not the only option but they are my favorites so far. I think Recharge needs to stop with their shenanigans and move their loyal customers to native subscriptions.

Note: At the end they gave us 2 more keys, we tried to implement our own customer portal cause Recharge's is super slow and we weren't able to finish it cause their API has tons of bugs... It's a nightmare and I don't recommend it at all