// GraalJS Script (engine type: 2)
//////// START "main()" /////////////////////////////////////////////////////////////////
main();
function main(){
//// == Config Retrieving / 工程コンフィグの参照 ==
const strAuthzSetting = configs.get ( "AuthzConfU" ); /// REQUIRED
engine.log( " AutomatedTask Config: Authz Setting: " + strAuthzSetting );
const strTokenId = configs.get( "strSetConfB" ); // required
const strCustomerEmail = configs.get( "strSetConfC1" ); // required
const strCustomerDescr = configs.get( "strSetConfC2" ); // required
const strCustomerName = configs.get( "strSetConfC3" ); // not
const pocketCustomerId = configs.getObject( "SelectConfD1" ); // required
const pocketCardBrand = configs.getObject( "SelectConfD2" ); // not
const pocketCardLast4 = configs.getObject( "SelectConfD3" ); // not
const pocketCardExp = configs.getObject( "SelectConfD4" ); // not *STRING/YMDATE
if( strTokenId === "" ){
throw new Error( "\n AutomatedTask ConfigError:" +
" Config {Token ID B} is empty \n" );
}
if( strCustomerEmail === "" ){
throw new Error( "\n AutomatedTask ConfigError:" +
" Config {CustomerEmail C1} is empty \n" );
}
if( strCustomerDescr === "" ){
throw new Error( "\n AutomatedTask ConfigError:" +
" Config {CustomerDescription C2} is empty \n" );
}
//// == Data Retrieving / ワークフローデータの参照 ==
// (nothing, except Expression Language config)
//// == Calculating / 演算 ==
/// POST /v1/customers
// https://stripe.com/docs/api/customers/create
// https://stripe.com/docs/api/authentication
// If you need to authenticate via bearer auth (e.g., for a cross-origin request),
// use -H "Authorization: Bearer sk_xxx" instead of -u sk_test_xxx.
// preparing for API Request
let apiUri = "https://api.stripe.com/v1/customers";
let apiRequest = httpClient.begin(); // HttpRequestWrapper
apiRequest = apiRequest.authSetting( strAuthzSetting ); // with "Authorization: Bearer XX"
// https://questetra.zendesk.com/hc/en-us/articles/360024574471-R2300#HttpRequestWrapper
apiRequest = apiRequest.formParam( "source", strTokenId );
apiRequest = apiRequest.formParam( "email", strCustomerEmail );
apiRequest = apiRequest.formParam( "description", strCustomerDescr );
apiRequest = apiRequest.formParam( "name", strCustomerName );
// throwing Request to the API (POST, GET, PUT, etc)
engine.log( " AutomatedTask Trying: POST " + apiUri );
const response = apiRequest.post( apiUri );
const responseCode = response.getStatusCode() + "";
engine.log( " AutomatedTask ApiResponse: Status " + responseCode );
if( responseCode !== "200"){
throw new Error( "\n AutomatedTask UnexpectedResponseError: " +
responseCode + "\n" + response.getResponseAsString() + "\n" );
} // C.F. https://stripe.com/docs/api/errors
// parsing Response Json
const responseStr = response.getResponseAsString() + "";
//engine.log( " DEBUG for api upgrade: \n" + responseStr );
const responseObj = JSON.parse( responseStr );
engine.log( " AutomatedTask ApiResponse:" +
" New CustomerObject ID: " + responseObj.id );
engine.log( " AutomatedTask ApiResponse:" +
" Card Brand: " + responseObj.sources.data[0].brand );
//// == Data Updating / ワークフローデータへの代入 ==
engine.setData( pocketCustomerId, responseObj.id );
if( pocketCardBrand !== null ){ // STRING
engine.setData( pocketCardBrand, responseObj.sources.data[0].brand );
}
if( pocketCardLast4 !== null ){ // STRING
engine.setData( pocketCardLast4, responseObj.sources.data[0].last4 );
}
if( pocketCardExp !== null ){ // STRING or YMDATE
if( pocketCardExp.matchDataType( "STRING" ) ){
engine.setData( pocketCardExp,
("0" + responseObj.sources.data[0].exp_month).slice(-2) + "/" +
responseObj.sources.data[0].exp_year );
}else{
engine.setData( pocketCardExp,
java.sql.Date.valueOf(
responseObj.sources.data[0].exp_year + "-" +
("0" + responseObj.sources.data[0].exp_month).slice(-2) + "-01"
)
);
}
}
} //////// END "main()" /////////////////////////////////////////////////////////////////
/*
Notes:
- Create a "Customer object" on Stripe using Token.
- An environment for recurring charges will be built on Stripe.
- Eg. place it after the "Payment card registration" step in the order handling workflow.
- A Tokenization mechanism (card registration form) is required.
- Refer to the sample below for how to implement the card registration form (tokenization).
- "Elements" (custom payment forms)
- https://stripe.com/docs/stripe-js
- https://support.questetra.com/tips/form-decoration-examples/#tokenize
- "Checkout" (forms hosted on Stripe)
- https://stripe.com/docs/payments/checkout
- Use the customer object ID (CustomerID) for flat-rate billing and usage billing.
- Can be obtained in this creation process. Example "cus_XXXXXYYYYYZZZZ"
Notes(ja):
- Token を利用して Stripe 上に "顧客オブジェクト" を生成します。
- Stripe上に「継続的な課金を実現するための環境」が構築されます。
- たとえば、受注対応ワークフローにおける「決済カードの登録」の工程の直後に配置します。
- Token 化の仕組み(カード登録フォーム)が別途必要です。
- カード登録フォーム(トークン化)の実装方法は以下のサンプルを参照してください。
- "Elements" (custom payment forms)
- https://stripe.com/docs/stripe-js
- https://support.questetra.com/ja/tips/form-decoration-examples/#tokenize
- "Checkout" (forms hosted on Stripe)
- https://stripe.com/docs/payments/checkout
- 定額課金や利用量課金の際には、顧客オブジェクトのID(CustomerID)を使用します。
- 生成工程で取得可能です。 例 "cus_XXXXXYYYYYZZZZ"
APPENDIX
- PCI DSS Compliance (SAQ A) is to ensure that payment card data never touches any server.
- https://stripe.com/docs/security/guide
- This automated step allows you to build a system that does not retain sensitive info with no-code.
- Set Stripe SecretKey in "HTTP Authentication" > "Token Fixed Value"
-"sk_live_XXXXXyyyyyZZZZZxxxxxYYYY" (32 letters)
- For the contents of the error code (ResponseCode other than 200)
- https://stripe.com/docs/api/errors
- When migrating from the old version (2020-06-03), add a new one instead of updating.
- The method of setting SecretKey has changed. (To be hidden)
- https://support.questetra.com/addons/stripe-customer-object-create/
- Add a new Addon to the workflow app (Maage Add-on > Definition of Service task > Add)
- Added "Token Fixed Value" at "HTTP Authz Settings"
- In the modeler, place the new version of the add-on and remove the old version of the add-on.
- Release workflow app.
APPENDIX-ja
- PCI DSS 「カード情報の非保持」(SAQ A)には、カード情報はいかなるサーバも経由してはいけません。
- https://stripe.com/docs/security/guide
- この自動工程を活用すれば、センシティブ情報を保持しない仕組み(完全委託)をノーコード開発できます。
- Stripe SecretKey は "HTTP認証設定" > "トークン直接指定" にてセットしてください
- "sk_live_XXXXXyyyyyZZZZZxxxxxYYYY" (32文字)
- エラーコード(200以外のResponseCode)の内容については以下を参照してください。
- https://stripe.com/docs/api/errors
- 旧版(2020-06-03)から移行する場合、更新ではなく、新規に追加してください。
- SecretKey の設定方法が変更されています。(隠蔽化)
- https://support.questetra.com/ja/addons/stripe-customer-object-create/
- ワークフローアプリに、新しいAddonを追加 (アドオンの管理 > サービスタスク定義ファイル > 追加)
- "HTTP認証設定" から "トークン直接指定" を追加
- モデラで、新版のアドオンを配置し、旧版のアドオンを削除
- ワークフローアプリをバージョンアップ(リリース)
*/
Pingback: Stripe: Customer, Charge – Questetra Support
Pingback: Stripe: Customer, Destination Charge – Questetra Support
Pingback: Stripe: Customer Object, Create – Questetra Support
Pingback: Stripe: Customers, Charge – Questetra Support