Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added endpoint for product details #20

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ Credentials within this project are managed using environment variables and [Git
# Access key from Stripe to access your Stripe resources
STRIPE_KEY=STRIPE_KEY

# The product ID which users are subscribed to.
EMAIL_PRODUCT_ID=STRIPE_KEY
# The ID of the price product object used in billing subscribers.
EMAIL_PRODUCT_PRICE_ID=STRIPE_KEY
ivelin marked this conversation as resolved.
Show resolved Hide resolved
```

## CI / CD Pipeline
Expand Down
80 changes: 80 additions & 0 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ <h2 id="swagger--summary-no-tags">Summary</h2>

</td>
</tr>
ivelin marked this conversation as resolved.
Show resolved Hide resolved
<tr>
<td class="swagger--summary-path" rowspan="1">
<a href="#path--product">/product</a>
</td>
<td>
<a href="#operation--product-get">GET</a>
</td>
<td>
<p>Retrieve notification product</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vickywane This doesn't need to be tied to notifications. Let's just say that it:

"Retrieve product and pricing information associated with a premium customer subscription."

In Stripe nomenclature, a subscription is the unique pairing of a customer account with a product entity. Products have a pricing attached to them which can be one time, recurring or some combination.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This text adjustment has been made.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still reads
"

Retrieve notification product

"


</td>
</tr>
<tr>
<td class="swagger--summary-path" rowspan="3">
<a href="#path--subscription">/subscription</a>
Expand Down Expand Up @@ -184,6 +196,74 @@ <h3 class="panel-title"><span class="operation-name">POST</span> <strong>/notifi
</div>
</div>

<span id="path--product"></span>
<div id="operation--product-get" class="swagger--panel-operation-get panel">
<div class="panel-heading">
<div class="operation-summary">Retrieve notification product</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vickywane similar comment here. It does not have to be tied to notifications. We may add other products in the future and this API should still return the product information given a customer subscription.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An adjustment has been made to the summary field in the openapi spec to correct this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange. This index.html file still shows <div class="operation-summary">Retrieve notification product</div>

<h3 class="panel-title"><span class="operation-name">GET</span> <strong>/product</strong></h3>
</div>
<div class="panel-body">
<section class="sw-operation-description">
<p>An endpoint to retrieve details about the Ambianic notifications product.</p>

</section>


<section class="sw-request-params">
<table class="table">
<thead>
<tr>
<th class="sw-param-name"></th>
<th class="sw-param-description"></th>
<th class="sw-param-type"></th>
<th class="sw-param-data-type"></th>
<th class="sw-param-annotation"></th>
</tr>
</thead>
<tbody>
<tr>
<td>
Access-Control-Allow-Origin
</td>
<td></td>
<td>header</td>
<td>
<span class="json-property-type">object</span>
<span class="json-property-range" title="Value limits"></span>

</td>
<td>
<span class="json-property-required"></span>
</td>
</tr>
</tbody>
</table>
</section>

<section class="sw-responses">

<dl>
<dt class="sw-response-200">
200 OK

</dt>
<dd class="sw-response-200">
<div class="row">
<div class="col-md-12">

</div>
</div>
<div class="row">

<div class="col-md-6 sw-response-model">
</div>

</div> </dd>
</dl>
</section>
</div>
</div>

<span id="path--subscription"></span>
<div id="operation--subscription-delete" class="swagger--panel-operation-delete panel">
<div class="panel-heading">
Expand Down
75 changes: 36 additions & 39 deletions netlify/functions/notification.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
require("dotenv").config();
const { ManagementClient } = require("auth0");
const moment = require("moment");
const { extendMoment } = require("moment-range");
const stripe = require("stripe")(process.env.STRIPE_KEY);


const Moment = extendMoment(moment);
const nodemailer = require("nodemailer");

const headers = {
Expand All @@ -31,59 +28,59 @@ const transport = nodemailer.createTransport({
const sender = process.env.SMTP_SENDER;

exports.handler = async (event, context, callback) => {
const { userId, notification } = JSON.parse(`${event.body}`);
const { userId, notification } = JSON.parse(`${event.body}`);

try {
const { user_metadata, email, nickname } = await management.getUser({ id: userId });
try {
const { user_metadata, email, nickname } = await management.getUser({ id: userId });

const { userSubscriptionId } = user_metadata;
const {status } = await stripe.subscriptions.retrieve(userSubscriptionId);
const { userSubscriptionId } = user_metadata;
const {status } = await stripe.subscriptions.retrieve(userSubscriptionId);

if (status === 'active') {
try {
await transport.sendMail({
from: sender,
to: email,
subject: notification.title,
text: "An object has been detected from your Ambianic Device",
html:
`
if (status === 'active') {
try {
await transport.sendMail({
from: sender,
to: email,
subject: notification.title,
text: "An object has been detected from your Ambianic Device",
html:
`
<div>
<h3> Hello ${nickname}</h3> <br />
<p> ${notification.message} today at <b> ${moment(new Date()).format("hh:mm A")}</b></p>
</div>
`,
});
});

callback(null, {
statusCode: 200,
headers,
body: JSON.stringify({
message: `Notification sent to ${email}`,
}),
});
} catch (error) {
console.log(error);
callback(null, {
statusCode: 422,
headers,
body: JSON.stringify({ error }),
});
}
} else {
callback(null, {
statusCode: 200,
statusCode: 403,
headers,
body: JSON.stringify({
message: `Notification sent to ${email}`,
message: "NO ACTIVE SUBSCRIPTION TO SEND EMAIL",
ivelin marked this conversation as resolved.
Show resolved Hide resolved
}),
});
} catch (error) {
console.log(error);
callback(null, {
statusCode: 422,
headers,
body: JSON.stringify({ error }),
});
}
} else {
} catch (error) {
callback(null, {
statusCode: 403,
headers,
body: JSON.stringify({
message: "NO ACTIVE SUBSCRIPTION TO SEND EMAIL",
}),
statusCode: 422,
body: JSON.stringify({ error: error.message }),
});
}
} catch (error) {
callback(null, {
headers,
statusCode: 422,
body: JSON.stringify({ error: error.message }),
});
}
};
37 changes: 37 additions & 0 deletions netlify/functions/product.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require("dotenv").config();
const stripe = require("stripe")(process.env.STRIPE_KEY);

const headers = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "Content-Type",
"Content-Type": "application/json",
};

exports.handler = async (event, context, callback) => {

if (event.httpMethod === "OPTIONS") {
// for preflight check
callback(null, {
statusCode: 200,
headers,
body: JSON.stringify({ status: "OK" }),
});
} else if (event.httpMethod === "GET") {

try {
const product = await stripe.products.retrieve(process.env.EMAIL_PRODUCT_ID);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vickywane instead of hardcoding the email product id in the deployment environment, let's just retrieve all information about user's subscription options along with product and price id. For now it's only email notifications, but we plan for that list of options to expand.

Copy link
Contributor Author

@vickywane vickywane Jun 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As explained in this comment, the renamed email-product-id has no direct relation with end-users. The product is created by the organization either through the Stripe API or Stripe dashboard.

It is used to identify the product that a user is subscribed to. The product being retrieved is what stores the data.

To handle multiple product-IDs, they can be stored as environment variables with respective names. However, product IDs are currently not stored in a user's meta_data.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then this method should take a generic product ID argument and return product information details.

EMAIL_PRODUCT_ID should not be hardcoded in the method implementation, but instead passed in as a productId argument from the client using this getProductInfo method.


callback(null, {
statusCode: 200,
headers,
body: JSON.stringify({ product }),
});
} catch (error) {
callback(null, {
statusCode: 500,
headers,
body: JSON.stringify({ error }),
});
}
}
};
2 changes: 1 addition & 1 deletion netlify/functions/subscription.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ exports.handler = async (
customer: customerID,
items: [
{
price: process.env.EMAIL_PRODUCT_ID,
price: process.env.EMAIL_PRICE_ID,
},
],
})
Expand Down
7 changes: 7 additions & 0 deletions openapi-docs/.openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,22 @@
README.md
docs/DefaultApi.md
docs/InlineObject.md
docs/InlineObject1.md
docs/InlineResponse200.md
docs/InlineResponse2001.md
docs/InlineResponse2002.md
docs/InlineResponse2003.md
docs/InlineResponse2004.md
docs/InlineResponse2004Product.md
src/ApiClient.js
src/api/DefaultApi.js
src/index.js
src/model/InlineObject.js
src/model/InlineObject1.js
src/model/InlineResponse200.js
src/model/InlineResponse2001.js
src/model/InlineResponse2002.js
src/model/InlineResponse2003.js
src/model/InlineResponse2004.js
src/model/InlineResponse2004Product.js
test/model/InlineResponse2004Product.spec.js
4 changes: 4 additions & 0 deletions openapi-docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,21 @@ Class | Method | HTTP request | Description
------------ | ------------- | ------------- | -------------
*AmbianicCloudApiCollection.DefaultApi* | [**createSubscription**](docs/DefaultApi.md#createSubscription) | **POST** /subscription | Subscribe a user to Ambianic&#39;s Premium Services
*AmbianicCloudApiCollection.DefaultApi* | [**deleteSubscription**](docs/DefaultApi.md#deleteSubscription) | **DELETE** /subscription | Delete an Ambianic&#39;s user subscription
*AmbianicCloudApiCollection.DefaultApi* | [**getNotificationProduct**](docs/DefaultApi.md#getNotificationProduct) | **GET** /product | Retrieve notification product
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vickywane in line with previous comments, this function name should be probably renamed to getProductInformation()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An adjustment has been made to the operationId field in the openapi spec to correct this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vickywane the change has not been reflected in the README.md file.
The path still links to docs/DefaultApi.md#getNotificationProduct instead of docs/DefaultApi.md#getProductInfo.

*AmbianicCloudApiCollection.DefaultApi* | [**getSubscriptionData**](docs/DefaultApi.md#getSubscriptionData) | **GET** /subscription | Get a user&#39;s subscription data
*AmbianicCloudApiCollection.DefaultApi* | [**sendNotification**](docs/DefaultApi.md#sendNotification) | **POST** /notification | Send an event detection notification


## Documentation for Models

- [AmbianicCloudApiCollection.InlineObject](docs/InlineObject.md)
- [AmbianicCloudApiCollection.InlineObject1](docs/InlineObject1.md)
- [AmbianicCloudApiCollection.InlineResponse200](docs/InlineResponse200.md)
- [AmbianicCloudApiCollection.InlineResponse2001](docs/InlineResponse2001.md)
- [AmbianicCloudApiCollection.InlineResponse2002](docs/InlineResponse2002.md)
- [AmbianicCloudApiCollection.InlineResponse2003](docs/InlineResponse2003.md)
- [AmbianicCloudApiCollection.InlineResponse2004](docs/InlineResponse2004.md)
- [AmbianicCloudApiCollection.InlineResponse2004Product](docs/InlineResponse2004Product.md)


## Documentation for Authorization
Expand Down
50 changes: 50 additions & 0 deletions openapi-docs/docs/DefaultApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Method | HTTP request | Description
------------- | ------------- | -------------
[**createSubscription**](DefaultApi.md#createSubscription) | **POST** /subscription | Subscribe a user to Ambianic&#39;s Premium Services
[**deleteSubscription**](DefaultApi.md#deleteSubscription) | **DELETE** /subscription | Delete an Ambianic&#39;s user subscription
[**getNotificationProduct**](DefaultApi.md#getNotificationProduct) | **GET** /product | Retrieve notification product
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vickywane another line that needs cleanup getNotificationProduct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be reflected in the new operation-id

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vickywane DefaultApi.md still reads Retrieve notification product for GET /product.

[**getSubscriptionData**](DefaultApi.md#getSubscriptionData) | **GET** /subscription | Get a user&#39;s subscription data
[**sendNotification**](DefaultApi.md#sendNotification) | **POST** /notification | Send an event detection notification

Expand Down Expand Up @@ -117,6 +118,55 @@ No authorization required
- **Accept**: application/json


## getNotificationProduct
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vickywane I see a lot of references to getNotificationProduct. Is the intention to have a method hardwired to getting notification product information or is the goal to have a more generic getProductInfo method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was yet to push the new updates from my local repository at the time of your review. I only called your attention to this comment.


> InlineResponse2004 getNotificationProduct(accessControlAllowOrigin, opts)

Retrieve notification product

An endpoint to retrieve details about the Ambianic notifications product.

### Example

```javascript
import AmbianicCloudApiCollection from 'ambianic_cloud_api_collection';

let apiInstance = new AmbianicCloudApiCollection.DefaultApi();
let accessControlAllowOrigin = *; // String |
let opts = {
'inlineObject1': new AmbianicCloudApiCollection.InlineObject1() // InlineObject1 |
};
apiInstance.getNotificationProduct(accessControlAllowOrigin, opts, (error, data, response) => {
if (error) {
console.error(error);
} else {
console.log('API called successfully. Returned data: ' + data);
}
});
```

### Parameters


Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**accessControlAllowOrigin** | **String**| |
**inlineObject1** | [**InlineObject1**](InlineObject1.md)| | [optional]

### Return type

[**InlineResponse2004**](InlineResponse2004.md)

### Authorization

No authorization required

### HTTP request headers

- **Content-Type**: application/json
- **Accept**: application/json


## getSubscriptionData

> InlineResponse200 getSubscriptionData(userStripeId, userSubscriptionId, accessControlAllowOrigin, accessControlAllowHeaders, contentType)
Expand Down
9 changes: 9 additions & 0 deletions openapi-docs/docs/InlineObject1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# AmbianicCloudApiCollection.InlineObject1

## Properties

Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**message** | **String** | | [optional]


Loading