Skip to content

Commit

Permalink
Subscriptions (#2)
Browse files Browse the repository at this point in the history
Start adding subscriptions, but NB that we need to come back and finish. This feature branch was cut short to get payments to prod faster.
  • Loading branch information
dgknght committed Feb 11, 2023
1 parent ab9d1f0 commit e3d4e55
Show file tree
Hide file tree
Showing 12 changed files with 433 additions and 101 deletions.
4 changes: 3 additions & 1 deletion .clj-kondo/config.edn
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
same-date?])
(cljs.test/is [called?
comparable?
seq-of-maps-like?])
seq-of-maps-like?
url-like?
conformant?])
(dgknght.app-lib.test/with-mail-capture [mailbox])
(dgknght.app-lib.web-mocks/with-web-mocks [calls])
(dgknght.payments.paypal.mocks/with-paypal-mocks [calls controller])]}
Expand Down
2 changes: 1 addition & 1 deletion project.clj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(defproject com.github.dgknght/payments "0.1.4"
(defproject com.github.dgknght/payments "0.1.5"
:description "Library for interacting with various payment providers"
:url "http://github.com/dgknght/payments"
:license {:name "Eclipse Public License"
Expand Down
52 changes: 52 additions & 0 deletions resources/fixtures/paypal/create-subscription-response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"id": "I-BW452GLLEP1G",
"status": "APPROVAL_PENDING",
"status_update_time": "2018-12-10T21:20:49Z",
"plan_id": "P-5ML4271244454362WXNWU5NQ",
"plan_overridden": false,
"start_time": "2018-11-01T00:00:00Z",
"quantity": "20",
"shipping_amount": {
"currency_code": "USD",
"value": "10.00"
},
"subscriber": {
"name": {
"given_name": "John",
"surname": "Doe"
},
"email_address": "customer@example.com",
"payer_id": "2J6QB8YJQSJRJ",
"shipping_address": {
"name": {
"full_name": "John Doe"
},
"address": {
"address_line_1": "2211 N First Street",
"address_line_2": "Building 17",
"admin_area_2": "San Jose",
"admin_area_1": "CA",
"postal_code": "95131",
"country_code": "US"
}
}
},
"create_time": "2018-12-10T21:20:49Z",
"links": [
{
"href": "https://www.paypal.com/webapps/billing/subscriptions?ba_token=BA-2M539689T3856352J",
"rel": "approve",
"method": "GET"
},
{
"href": "https://api-m.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G",
"rel": "edit",
"method": "PATCH"
},
{
"href": "https://api-m.paypal.com/v1/billing/subscriptions/I-BW452GLLEP1G",
"rel": "self",
"method": "GET"
}
]
}
4 changes: 3 additions & 1 deletion src/dgknght/payments/paypal.clj
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@

(defn config
[& ks]
(get-in *config* (cons :paypal ks)))
(if (seq ks)
(get-in *config* (cons :paypal ks))
(:paypal *config*)))
72 changes: 64 additions & 8 deletions src/dgknght/payments/paypal.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
(:refer-clojure :exclude [js->clj])
(:require [cljs.core :as c]
[cljs.core.async :as a]
[cljs.spec.alpha :as s]
[camel-snake-kebab.core :refer [->kebab-case-keyword]]
[camel-snake-kebab.extras :refer [transform-keys]]))

Expand Down Expand Up @@ -30,24 +31,81 @@

(defn- buttons-config
[{:keys [create-order
create-subscription
on-approve
on-cancel
style]}]
(clj->js
(cond-> {"createOrder" (fn [data actions]
(->promise create-order
{:data (js->clj data)
:actions (js->clj actions)}))
"onApprove" (fn [data actions]
(cond-> {"onApprove" (fn [data actions]
(->promise on-approve
{:data (js->clj data)
:actions (js->clj actions)}))}
create-order (assoc "createOrder"
(fn [data actions]
(->promise create-order
{:data (js->clj data)
:actions (js->clj actions)})))
create-subscription (assoc
"createSubscription"
(fn [data actions]
(->promise create-subscription
{:data (js->clj data)
:actions (js->clj actions)})))
on-cancel (assoc
"onCancel" (fn [data]
(->promise on-cancel
{:data (js->clj data)})))
style (assoc "style" style))))

(s/def ::element-id string?)
(s/def ::on-approve fn?)
(s/def ::on-cancel fn?)
(s/def ::on-init fn?)
(s/def ::on-click fn?)
(s/def ::on-shipping-change fn?)
(s/def ::create-order fn?)
(s/def ::create-subscription fn?)
(s/def ::layout #{"vertical" "horizontal"})
(s/def ::color #{"gold" "blue" "silver" "white" "black"})
(s/def ::shape #{"rect" "pill"})
(s/def ::height (s/and integer?
#(<= 25 % 55)))
(s/def ::label #{"paypal"
"checkout"
"buynow"
"pay"
"installment"})
(s/def ::tagline boolean?)
(s/def ::style (s/keys :opt-un [::layout
::color
::shape
::height
::label]))
(s/def ::on-error fn?)
(s/def ::buttons-options
(s/and
(s/keys :req-un [::element-id
::on-approve]
:opt-un [::create-order
::create-subscription
::on-cancel
::on-init
::on-click
::on-shipping-change])
#(or (:create-order %)
(:create-subscription %))
#(not
(and (:create-order %)
(:create-subscription %)))))

(defn- valid-buttons-args?
[args]
(if-let [exp (s/explain-data ::buttons-options args)]
(do
(.error js/console (pr-str exp))
false)
true))

(defn buttons
"Create and return an instance that manages
the PayPal buttons.
Expand All @@ -56,9 +114,7 @@
{:create-order fn-that-initializes-payment
:on-approve fn-that-finalizes-payment})"
[{:keys [element-id] :as args}]
{:pre [(:element-id args)
(:create-order args)
(:on-approve args)]}
{:pre [(valid-buttons-args? args)]}

(if-let [paypal (.-paypal js/window)]
(let [btns (.Buttons paypal (buttons-config args))]
Expand Down
35 changes: 19 additions & 16 deletions src/dgknght/payments/paypal/api.clj
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,16 @@
(throw (ex-info "Unable to acquire an access token"
{:response clj-body})))))

(defn- create-order-url []
(defn- build-url
[& segments]
(-> (base-uri)
uri
(assoc :path "/v2/checkout/orders")
(assoc :path (string/join "/" (cons "" segments)))
str))

(defn- create-order-url []
(build-url "v2" "checkout" "orders"))

(defn create-order
"Create a PayPal order
order - contains the PayPal order"
Expand All @@ -247,10 +251,7 @@

(defn- capture-payment-url
[order-id]
(-> (base-uri)
uri
(assoc :path (str "/v2/checkout/orders/" order-id "/capture"))
str))
(build-url "v2" "checkout" "orders" order-id "capture"))

(defn capture-payment
[order-id]
Expand All @@ -264,10 +265,7 @@
:response clj-body})))))

(defn- gen-client-token-url []
(-> (base-uri)
uri
(assoc :path "/v1/identity/generate-token")
str))
(build-url "v1" "identity" "generate-token"))

(defn generate-client-token []
(let [{:keys [body] :as res}
Expand All @@ -281,12 +279,8 @@
(defn- web-profiles-url
([] (web-profiles-url nil))
([id]
(let [segments (cond-> ["" "v1" "payment-experience" "web-profiles"]
id (conj id))]
(-> (base-uri)
uri
(assoc :path (string/join "/" segments))
str))))
(apply build-url (cond-> ["v1" "payment-experience" "web-profiles"]
id (conj id)))))

(defn web-profiles
([]
Expand All @@ -303,3 +297,12 @@
(http-post (web-profiles-url)
{:form-params (jsonify add)
:oauth-token (generate-access-token)})))))

(defn- create-subscription-url []
(build-url "v1" "billing" "subscriptions"))

(defn create-subscription
[sub]
(:clj-body (http-post (create-subscription-url)
{:form-params (jsonify sub)
:oauth-token (generate-access-token) })))
33 changes: 0 additions & 33 deletions src/dgknght/payments/paypal/web.clj

This file was deleted.

0 comments on commit e3d4e55

Please sign in to comment.