WIP: Order.{createRequest,capture}
This commit is contained in:
parent
19cfcabc27
commit
e1fa70d495
40
README.md
40
README.md
|
@ -46,7 +46,11 @@ PPC.Subscriptions.createRequest({
|
|||
```txt
|
||||
PayPal.init(client_id, client_secret, 'sandbox|live', defaults);
|
||||
PayPal.request({ method, url, headers, json });
|
||||
```
|
||||
|
||||
### Subscrptions (Recurring Payments)
|
||||
|
||||
```txt
|
||||
// Webhook 'event_type':
|
||||
|
||||
PayPal.Product.create({ ... }); // CATALOG.PRODUCT.CREATED
|
||||
|
@ -66,11 +70,47 @@ PayPal.Subscription.details(id);
|
|||
PayPal.Subscription.cancel(id, { reason });
|
||||
```
|
||||
|
||||
### Orders (One-Time Payments)
|
||||
|
||||
```txt
|
||||
PayPal.Order.createRequest({ ... }); // ??
|
||||
```
|
||||
|
||||
See also:
|
||||
|
||||
- <https://developer.paypal.com/docs/api/orders/v2/#orders_create>
|
||||
- <https://developer.paypal.com/docs/api/orders/v2/#definition-purchase_unit_request>
|
||||
- <https://developer.paypal.com/docs/api/orders/v2/#definition-order_application_context>
|
||||
|
||||
# Redirects
|
||||
|
||||
- `return_url`
|
||||
- `cancel_url`
|
||||
|
||||
### Orders
|
||||
|
||||
#### `return_url`
|
||||
|
||||
Order Request `return_url` will be called with the `token` query param as the
|
||||
`order_id`:
|
||||
|
||||
```txt
|
||||
https://example.com/redirects/paypal-checkout/return
|
||||
?token=XXXXXXXXXXXXXXXXX
|
||||
&PayerID=XXXXXXXXXXXXX
|
||||
```
|
||||
|
||||
Again, `token` is the `order_id`.
|
||||
|
||||
#### `cancel_url`
|
||||
|
||||
The `cancel_url` will have the same query params as the `return_url`.
|
||||
|
||||
Also, PayPal presents the raw `cancel_url` and will NOT update the order status.
|
||||
It's up to you to confirm with the user and change the status to `CANCELLED`.
|
||||
|
||||
### Subscriptions
|
||||
|
||||
#### `return_url`
|
||||
|
||||
Subscription Request `return_url` will include the following:
|
||||
|
|
|
@ -114,6 +114,69 @@ function enumify(obj) {
|
|||
}
|
||||
*/
|
||||
|
||||
let Order = {};
|
||||
Order.intents = {
|
||||
CAPTURE: "CAPTURE",
|
||||
AUTHORIZE: "AUTHORIZE",
|
||||
};
|
||||
// See
|
||||
// https://developer.paypal.com/docs/api/orders/v2/#orders_create
|
||||
// https://developer.paypal.com/docs/api/orders/v2/#definition-purchase_unit_request
|
||||
// https://developer.paypal.com/docs/api/orders/v2/#definition-order_application_context
|
||||
Order.createRequest = async function (order) {
|
||||
if (!order.intent) {
|
||||
order.intent = Order.intents.CAPTURE;
|
||||
}
|
||||
if (!order.purchase_units?.length) {
|
||||
throw new Error("must have 'purchase_units'");
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
intent: "CAPTURE",
|
||||
purchase_units: [
|
||||
{
|
||||
amount: {
|
||||
currency_code: "USD",
|
||||
value: "100.00",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
*/
|
||||
return await PayPal.request({
|
||||
method: "POST",
|
||||
url: `/v2/checkout/orders`,
|
||||
json: order,
|
||||
})
|
||||
.then(must201or200)
|
||||
.then(justBody);
|
||||
};
|
||||
|
||||
Order.details = async function (id) {
|
||||
return await PayPal.request({
|
||||
url: `/v2/checkout/orders/${id}`,
|
||||
json: true,
|
||||
})
|
||||
.then(must201or200) // 200
|
||||
.then(justBody);
|
||||
};
|
||||
|
||||
/**
|
||||
* Captures (finalizes) an approved order.
|
||||
* @param {String} id
|
||||
* @param {any} body
|
||||
*/
|
||||
Order.capture = async function (id, { note_to_payer, final_capture }) {
|
||||
return await PayPal.request({
|
||||
method: "POST",
|
||||
url: `/v2/checkout/orders/${id}/capture`,
|
||||
json: { note_to_payer, final_capture },
|
||||
})
|
||||
.then(must201or200)
|
||||
.then(justBody);
|
||||
};
|
||||
|
||||
let Product = {};
|
||||
|
||||
// SaaS would be type=SERVICE, category=SOFTWARE
|
||||
|
@ -447,6 +510,7 @@ Subscription.cancel = async function _showProductDetails(id, { reason }) {
|
|||
|
||||
module.exports.init = PayPal.init;
|
||||
module.exports.request = PayPal.request;
|
||||
module.exports.Order = Order;
|
||||
module.exports.Plan = Plan;
|
||||
module.exports.Product = Product;
|
||||
module.exports.Subscription = Subscription;
|
||||
|
|
|
@ -11,7 +11,7 @@ if (!process.env.PAYPAL_CLIENT_ID) {
|
|||
}
|
||||
|
||||
let PayPal = require("../");
|
||||
let { Plan, Product, Subscription } = PayPal;
|
||||
let { Plan, Product /*, Subscription*/ } = PayPal;
|
||||
|
||||
async function test() {
|
||||
let products = await Product.list();
|
||||
|
@ -48,7 +48,11 @@ async function test() {
|
|||
}
|
||||
|
||||
if (require.main === module) {
|
||||
PayPal.init(process.env.PAYPAL_CLIENT_ID, process.env.PAYPAL_CLIENT_SECRET);
|
||||
PayPal.init(
|
||||
process.env.PAYPAL_CLIENT_ID,
|
||||
process.env.PAYPAL_CLIENT_SECRET,
|
||||
"sandbox"
|
||||
);
|
||||
test().catch(function (err) {
|
||||
console.error("Something bad happened:");
|
||||
console.error(JSON.stringify(err, null, 2));
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
"use strict";
|
||||
|
||||
require("dotenv").config({ path: ".env" });
|
||||
require("dotenv").config({ path: ".env.secret" });
|
||||
|
||||
if (!process.env.PAYPAL_CLIENT_ID) {
|
||||
console.error(
|
||||
"Please copy example.env to .env and update the values from the PayPal API Dashboard at https://developer.paypal.com/developer/applications"
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let PayPal = require("../");
|
||||
let { Order } = PayPal;
|
||||
|
||||
async function test() {
|
||||
let ppcOrder = await Order.createRequest({
|
||||
application_context: {
|
||||
brand_name: "Bliss via The Root Group, LLC",
|
||||
shipping_preference: "NO_SHIPPING",
|
||||
// ("checkout with paypal") or "BILLING" (credit card) or NO_PREFERENCE
|
||||
landing_page: "LOGIN",
|
||||
user_action: "PAY_NOW",
|
||||
return_url: `https://example.com/api/redirects/paypal-checkout/return`,
|
||||
cancel_url: `https://example.com/api/redirects/paypal-checkout/cancel`,
|
||||
},
|
||||
purchase_units: [
|
||||
{
|
||||
request_id: 0,
|
||||
custom_id: "xxxx", // Our own (User x Product) ID
|
||||
description: "1 year of pure Bliss", // shown in PayPal Checkout Flow UI
|
||||
soft_descriptor: "Bliss", // on the charge (credit card) statement
|
||||
amount: {
|
||||
currency_code: "USD",
|
||||
value: "10.00",
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
console.info();
|
||||
console.info("Order:");
|
||||
console.info(JSON.stringify(ppcOrder, null, 2));
|
||||
|
||||
// wait for user to click URL and accept
|
||||
await new Promise(function (resolve) {
|
||||
console.info();
|
||||
console.info("Please approve the order at the following URL:");
|
||||
console.info();
|
||||
console.info(
|
||||
"Approve URL:",
|
||||
ppcOrder.links.find(function (link) {
|
||||
return "approve" === link.rel;
|
||||
}).href
|
||||
);
|
||||
console.info("Username:", process.env.PAYPAL_SANDBOX_EMAIL);
|
||||
console.info("Password:", process.env.PAYPAL_SANDBOX_PASSWORD);
|
||||
console.info();
|
||||
console.info("Did you approve it? Hit the <any> key to continue...");
|
||||
console.info();
|
||||
process.stdin.once("data", resolve);
|
||||
});
|
||||
process.stdin.pause();
|
||||
|
||||
let ppcCapture = await Order.capture(ppcOrder.id, {
|
||||
note_to_payer: undefined,
|
||||
final_order: true,
|
||||
});
|
||||
|
||||
console.info();
|
||||
console.info("Capture:");
|
||||
console.info(JSON.stringify(ppcCapture, null, 2));
|
||||
|
||||
console.info();
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
PayPal.init(
|
||||
process.env.PAYPAL_CLIENT_ID,
|
||||
process.env.PAYPAL_CLIENT_SECRET,
|
||||
"sandbox"
|
||||
);
|
||||
test().catch(function (err) {
|
||||
console.error("Something bad happened:");
|
||||
console.error(err);
|
||||
console.error(JSON.stringify(err, null, 2));
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue