Episode 527: Calling PayPal Invoicing API at Auto-step

Tuesday, March 21, 2017

PayPal as a Billing System

"PayPal Invoice" is very useful.

Just by logging-in to PayPal and entering "destination email address" and "details of sold item", anyone can easily send the invoice. It can be said that it is one of a few settlement methods that can flexibly deal with "a little consignment work" or "special discounts". It almost makes me think that procedures of shopping at EC site is rather more difficult. Moreover, there is no need to tell "credit card number" from the buyer to the seller.

However, if dozens of issuance must be, it will inevitably be troublesome. (Its "flexibility" serves harmful.)

If the billing contents were exactly the same, there was a function to process collectively, but if the contents are subtly different from each other, you have to set the billing information one by one. However, repetition of manual work falls into error, by all means.

Automate invoice creation and transmission

In the previous article (*), I introduced you "a mechanism to automatically generate a request that "Generate a PayPal invoice" and transmit it to the PayPal system.
* Episode 525: How to Send OAuth2 Request from Automatic Step

In this article, I would like to study further about "a mechanism to automatically send a request that "generate and send PayPal invoice to the buyer". (Programming knowledge is required)

[Entry reception system]

Business process that has been eliminated manual work to the utmost

The Business Process definition I'm introducing here is an "event participation reception work" such as "seminar" and "study meeting".

Although it is obvious if you look at the Workflow diagram, it is a mechanism that an Issue begins to flow each time "input to the Web form" is done. And then only when "entry requiring billing", it is diverted to the "flow of invoice-generation". (OR split)

Many of the Tasks placed in the Workflow diagram are "automatic Task" (grayed), "human Tasks" (light blue) are "1. Bill check" and "2. Payment check" only. Moreover, regarding "1.Bill check", it is a human task that is set to automatically be finished in 5 minutes, and any concrete work is not stipulated in normal time. (To enhance check by prolonging deadline time when unauthorized access increases, or so.)

Sample codes

All the five automatic Steps, such as "Subject set", "Honorific name set", "Receipt issue date set", "Participation certificate PDF generation" and "Receipt PDF generation", are [Service Task] that is standard of Questetra.

The two automatic Steps, "Invoice generation " and "Invoice transmission" are "Script Task", so you need to set server-side JavaScript. In the script, communication with the PayPal Invoicing API is stipulated.

<Setting example of Script Task "Invoice generation">
// PayPal Invoicing API CREATE (ver. 20170314) 
// (c) 2017, Questetra, Inc. (the MIT License) 

var sandboxmode = false; // true or false 

//// == Config & Retrieving == 
// Get Your "REST API app" via PayPal Dashboard 
// https://developer.paypal.com/developer/applications/ 
var clientId = "Your-Client-Id-Your-Client-Id-Your-Client-Id-Your-Client-Id-Your-Client-Id-Your-"; 
var secret = "Your-Secret-Your-Secret-Your-Secret-Your-Secret-Your-Secret-Your-Secret-Your-Sec"; 
var clientIdSandbox = "Your-Client-Id-Your-Client-Id-Your-Client-Id-Your-Client-Id-Your-Client-Id-Your-"; 
var secretSandbox = "Your-Secret-Your-Secret-Your-Secret-Your-Secret-Your-Secret-Your-Secret-Your-Sec"; 
if( sandboxmode ){ clientId = clientIdSandbox; secret = secretSandbox; } 

// Your Info 
var merchantEmail = "support@questetra.com"; 
var merchantEmailSandbox = "qstore-paypal-facilitator@questetra.com"; 
if( sandboxmode ){ merchantEmail = merchantEmailSandbox; } 
//var merchantBusinessName = "Questetra, Inc."; 
var merchantBusinessName = "株式会社クエステトラ"; 
//var merchantAddress2 = "Nakagyo-ku Oike-dori-Ainomachi"; // first line 
var merchantAddress1 = "中京区御池通間之町東入"; // second line 
//var merchantAddress1 = "Takamiya-cho 206 Oike Bldg 4th"; 
var merchantAddress2 = "高宮町206 御池ビル4階"; 
//var merchantAddressCity = "Kyoto"; 
var merchantAddressCity = "京都市"; 
//var merchantAddressState = "KYOTO"; 
var merchantAddressState = "京都府"; 
var merchantAddressPC = "604-0835"; 
var merchantAddressCC = "JP"; 
var merchantWebsite = "https://www.questetra.com/corp/"; 
// for Link to BPMS on PayPal 
var merchantMemo = "https://YourPlatformID.questetra.net/PE/Workitem/list?processInstanceId="; 
merchantMemo += processInstance.getProcessInstanceId(); 


// Customer Info 
//var billingLanguage = "en_US"; 
var billingLanguage = "ja_JP"; 
var billingEmail = data.get( "q_billingEmail" ) + ""; 
var billingName1 = data.get( "q_billingName1" ) + ""; 
var billingBusinessName = data.get( "q_billingBusinessName" ) + ""; 

// Items Info 
//var itemUnitPriceCurrency = "USD"; 
var itemUnitPriceCurrency = "JPY"; 
//var itemTaxName = "JCT"; 
var itemTaxName = "消費税"; 
var itemTaxPercent = 8; 
var itemName = data.get( "q_item" ).get(0).getDisplay() + "";
var itemQuantity = 1; // number
var itemUnitPrice = data.get( "q_item" ).get(0).getValue() + ""; // string

// Invoice Info 
var invoiceNumber = processInstance.getProcessInstanceId() + ""; // string 
var invoiceDate = data.get( "q_invoiceDate" ) + " JST"; // yyyy-MM-dd z 
var termType = "NET_10"; //"DUE_ON_RECEIPT"; 
var logoUrl = "https://www.questetra.com/wp-content/uploads/2017/03/Corporate-logo-100x100.png"; 


//// == Calculating == 
var accessLog = ""; 

// Getting OAuth2 Token via client_credentials grant 
var uriToken = "https://api.paypal.com/v1/oauth2/token"; 
var uriTokenSandbox = "https://api.sandbox.paypal.com/v1/oauth2/token"; 
if( sandboxmode ){ uriToken = uriTokenSandbox; } 
var response = httpClient.begin() 
.basic( clientId, secret ) 
.formParam( "grant_type", "client_credentials" ) 
.post( uriToken ); 
accessLog += "---POST request--- " + response.getStatusCode() + "\n"; 
accessLog += response.getResponseAsString() + "\n"; 
accessLog += "\n"; 
var oauthTokenObj = JSON.parse( response.getResponseAsString() ); 
var oauthToken = oauthTokenObj.access_token; 
accessLog += "oauthToken: " + oauthToken + "\n"; 
accessLog += "\n"; 

// Create invoice 
var invoiceObj = {}; 
invoiceObj.number = invoiceNumber; 
invoiceObj.invoice_date = invoiceDate; 
invoiceObj.payment_term = {}; 
invoiceObj.payment_term.term_type = termType; 
invoiceObj.logo_url = logoUrl; 
invoiceObj.merchant_memo = merchantMemo; 

invoiceObj.merchant_info = {}; 
invoiceObj.merchant_info.email = merchantEmail; 
invoiceObj.merchant_info.business_name = merchantBusinessName; 
invoiceObj.merchant_info.address = {}; 
invoiceObj.merchant_info.address.line1 = merchantAddress1; 
invoiceObj.merchant_info.address.line2 = merchantAddress2; 
invoiceObj.merchant_info.address.city = merchantAddressCity; 
invoiceObj.merchant_info.address.state = merchantAddressState; 
invoiceObj.merchant_info.address.postal_code = merchantAddressPC; 
invoiceObj.merchant_info.address.country_code = merchantAddressCC; 
invoiceObj.merchant_info.website = merchantWebsite; 
invoiceObj.billing_info = []; 
invoiceObj.billing_info[0] = {}; 
invoiceObj.billing_info[0].email = billingEmail; 
invoiceObj.billing_info[0].first_name = billingName1; 
// invoiceObj.billing_info[0].last_name = billingName2; 
invoiceObj.billing_info[0].business_name = billingBusinessName; 
invoiceObj.billing_info[0].language = billingLanguage; 
invoiceObj.items = []; 
invoiceObj.items[0] = {}; 
invoiceObj.items[0].name = itemName; 
// invoiceObj.items[0].description =itemDescription; 
invoiceObj.items[0].quantity = itemQuantity; 
invoiceObj.items[0].unit_price = {}; 
invoiceObj.items[0].unit_price.currency = itemUnitPriceCurrency; 
invoiceObj.items[0].unit_price.value = itemUnitPrice; 
invoiceObj.items[0].tax = {}; 
invoiceObj.items[0].tax.name = itemTaxName; 
invoiceObj.items[0].tax.percent = itemTaxPercent; 
var uriCreate = "https://api.paypal.com/v1/invoicing/invoices/"; 
var uriCreateSandbox = "https://api.sandbox.paypal.com/v1/invoicing/invoices/"; 
if( sandboxmode ){ uriCreate = uriCreateSandbox; } 
var responseCreate = httpClient.begin() 
.bearer( oauthToken ) 
.body( JSON.stringify( invoiceObj ), "application/json" ) 
.post( uriCreate ); 

accessLog += "---POST request--- " + responseCreate.getStatusCode() + "\n"; 
accessLog += JSON.stringify( invoiceObj ) + "\n"; 
accessLog += "\n"; 
accessLog += responseCreate.getResponseAsString() + "\n"; 
accessLog += "\n"; 
var paypalIdObj = JSON.parse( responseCreate.getResponseAsString() ); 
var paypalId = paypalIdObj.id; 
accessLog += "paypalId: " + paypalId + "\n"; 
accessLog += "\n"; 


//// == Data Updating == 
retVal.put( "q_accessLog", accessLog ); 
retVal.put( "q_paypalId", paypalId ); 

<Setting example of Script Task "Invoice transmission>
// PayPal Invoicing API SEND (ver. 20170303) 
// (c) 2017, Questetra, Inc. (the MIT License) 
var sandboxmode = false; // true or false 

//// == Config & Retrieving == 
// Your "REST API app" on PayPal Dashboard 
// https://developer.paypal.com/developer/applications/ 
var clientId = "Your-Client-Id-Your-Client-Id-Your-Client-Id-Your-Client-Id-Your-Client-Id-Your-"; 
var secret = "Your-Secret-Your-Secret-Your-Secret-Your-Secret-Your-Secret-Your-Secret-Your-Sec"; 
var clientIdSandbox = "Your-Client-Id-Your-Client-Id-Your-Client-Id-Your-Client-Id-Your-Client-Id-Your-"; 
var secretSandbox = "Your-Secret-Your-Secret-Your-Secret-Your-Secret-Your-Secret-Your-Secret-Your-Sec"; 
if( sandboxmode ){ clientId = clientIdSandbox; secret = secretSandbox; } 

var paypalId = data.get( "q_paypalId" ) + ""; 


//// == Calculating == 
var accessLog = ""; 

// Getting OAuth2 Token via client_credentials grant 
var uriToken = "https://api.paypal.com/v1/oauth2/token"; 
var uriTokenSandbox = "https://api.sandbox.paypal.com/v1/oauth2/token"; 
if( sandboxmode ){ uriToken = uriTokenSandbox; } 
var response = httpClient.begin() 
.basic( clientId, secret ) 
.formParam( "grant_type", "client_credentials" ) 
.post( uriToken ); 
accessLog += "---POST request--- " + response.getStatusCode() + "\n"; 
accessLog += response.getResponseAsString() + "\n"; 
accessLog += "\n"; 
var oauthTokenObj = JSON.parse( response.getResponseAsString() ); 
var oauthToken = oauthTokenObj.access_token; 
accessLog += "oauthToken: " + oauthToken + "\n"; 
accessLog += "\n"; 

// Send invoice 
var uriSend = "https://api.paypal.com/v1/invoicing/invoices/" + paypalId + "/send"; 
var uriSendSandbox = "https://api.sandbox.paypal.com/v1/invoicing/invoices/" + paypalId + "/send"; 
if( sandboxmode ){ uriSend = uriSendSandbox; } 
var responseSend = httpClient.begin() 
.bearer( oauthToken ) 
.post( uriSend ); 

accessLog += "---POST request--- " + responseSend.getStatusCode() + "\n"; 
accessLog += responseSend.getResponseAsString() + "\n"; 
accessLog += "\n"; 


//// == Data Updating == 
retVal.put( "q_accessLog2", accessLog ); 

<Web Form screen>

<PayPal invoice>

<Data Items list>


[Free Download]
<Similar Models>
<<Related Articles>>

[Japanese Entry (和文記事)]