Skip to content

Instantly share code, notes, and snippets.

@jimmijazz
Created February 3, 2023 22:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jimmijazz/a4ae1b96bf521538f8df5b9d13c7e88f to your computer and use it in GitHub Desktop.
Save jimmijazz/a4ae1b96bf521538f8df5b9d13c7e88f to your computer and use it in GitHub Desktop.
Capture payment for Active Subscribers based on charge_delay and when their order was created
/* Customer orders are recieved as "authorized". The number of days left in their trial is passed as a line
item prop charge_delay. This cron job checks each hour for any orders that are still in authorized state.
If the (order date + charge_delay) is > current date, their trial has ended and we capture payment if
they are still have the "Active Subscriber" tag.
*/
async function captureUnpaidOrders() {
console.log('Debug: Getting unpaid orders');
/* Finds any orders where financial status is authorized.
Then checks if the created_at date + the charge_delay is less than the current date.
If true, capture the payment.
*/
let apiAccessToken = process.env.API_ACCESS_TOKEN;
let store = process.env.STORE;
let apiVersion = process.env.API_VERSION;
const endpoint = `https://${store}.myshopify.com/admin/api/${apiVersion}/graphql.json`;
const graphQLClient = new GraphQLClient(endpoint, {
headers: {
"Content-Type": "application/json",
"X-Shopify-Access-Token": apiAccessToken
},
});
let query = gql`
query {
orders(first:50, reverse:true, query:"financial_status:authorized") {
edges {
node {
id
displayFinancialStatus
createdAt
transactions(first:5){
id
amountSet{
shopMoney {
amount
currencyCode
}
}
}
lineItems(first:1) {
edges {
node {
customAttributes {
key
value
}
}
}
}
customer {
tags
}
}
}
}
}
`;
let orders_to_capture = []; // Array to store matching orders
let orders_to_cancel = []; // Array to store orders that are past the charge delay but customer is inactive subscriber
const data = await graphQLClient.request(query);
let orders = data['orders']['edges'];
if (orders.length > 0) {
orders.forEach(function (node) {
let order = node['node'];
let lineItems = order['lineItems']['edges'];
let customAttributes = lineItems[0]['node']['customAttributes'];
// Get value of object that has a "key" of "charge_delay"
let charge_delay = customAttributes.find(function (obj) { return obj.key === 'charge_delay'; }).value;
console.log(`Charge Delay: ${charge_delay}`);
let orderID = order['id'];
let createdAt = order['createdAt'];
// Transaction details
let transctionID = order['transactions'][0]['id'];
let transactionAmount = order['transactions'][0]['amountSet']['shopMoney']['amount'];
let transactionCurrencyCode = order['transactions'][0]['amountSet']['shopMoney']['currencyCode'];
// Financial details
let financialStatus = order['displayFinancialStatus'];
// Check if orderData + charge_delay days is greater than current time
let orderDate = Moment(createdAt).format('MMMM Do YYYY, h:mm:ss a');
let orderDatePlusChargeDelay = Moment(createdAt).add(charge_delay, 'days').format('MMMM Do YYYY, h:mm:ss a');
let currentTime = Moment().format('MMMM Do YYYY, h:mm:ss a');
// Customer details
let customer = order['customer'];
let customerTagsArray = customer['tags'].split(',');
// console.log(`Order Date: ${orderDate}`);
// console.log(`Order Date + Charge Delay: ${orderDatePlusChargeDelay}`);
// console.log(`Current Time: ${currentTime}`);
// console.log(`Current time is less than charge delay: ${Moment(currentTime).isBefore(orderDatePlusChargeDelay)}`);
// Create array of orders to capture
if (Moment(currentTime).isBefore(orderDatePlusChargeDelay)) { // If current time is less than order date + charge delay
if (customer.tags.includes("Active Susbcriber")) { // Check customer is still active subscriber
// Customer
orders_to_capture.push({
orderID: orderID,
transactionID: transctionID,
transactionAmount: transactionAmount,
transactionCurrencyCode: transactionCurrencyCode
});
}
};
});
};
// Capture our orders
console.log(`Debug: capturing orders - ${orders_to_capture.length}`)
orders_to_capture.forEach(async function (order) {
// Graphql mutation to capture orders
query = gql`
mutation orderCapture($input: OrderCaptureInput!) {
orderCapture(input: $input) {
transaction {
id
}
userErrors {
field
message
}
}
}
`;
let variables = {
"input": {
"amount": order.transactionAmount,
"currency": order.transactionCurrencyCode,
"id": order.orderID,
"parentTransactionId": order.transactionID
}
};
const data = await graphQLClient.request(query, variables).then((data) => {
console.log(data);
if (data['response']['errors']) {
console.log(`Error: ${data['response']['errors']}`);
}
}).catch((error) => {
console.log(error);
}
);
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment