Friday, 26 February 2016

Accepting payments with Stripe in APEX, Part 3

Hooking everything up in APEX

In part 1 of the series, we set up a form that would accept payment information. In part 2 we set up a PL/SQL API. Now, the final step is that we want to actually charge the card after the user submits the payment information, which is relatively straight forward.

First, we can set up a couple of substitution strings for our stripe secret and the wallet information




Next, add a new (hidden) item to the page that we can set the token into it (I called mine "P1_PMT_TOKEN"). Once that is on the page, we can modify our existing dynamic action (from part 1), so the code now looks like:

var handler = StripeCheckout.configure({
    key: 'pk_test_oXgwgmJbBmhzODwHxoKE8zAz',
    locale: 'auto',
    token: function(token) {
        $s('P1_PMT_TOKEN', token.id);
    }
});

handler.open({
    name: 'Demo Site',
    description: '2 widgets',
    currency: "aud",
    amount: 2000
});

Now, after they click the Pay button, we'll want to trigger the charge - where we need to call some PL/SQL. This can be done either from a page submission, or more than likely you will want to trigger this from a dynamic action. This is done easily with a change action on your P1_PMT_TOKEN page item.

begin

    stripe_api.set_secret(:STRIPE_TOKEN);
    
    stripe_api.charge_card (
        p_amount => 2000
      , p_source => :P1_PMT_TOKEN
      , p_description => 'Charged from a D.A'
      , p_wallet_path => :WALLET_PATH
      , p_wallet_password => :WALLET_PASSWORD
    );

end;

Now, if we submit a payment and look in our dashboard we will see the payment appear.



Finally, you may like to parse the response to return some more valuable information. Such as, the charge response includes a status field which according to the documentation can either be "succeeded" or "failed". APEX comes with APEX_JSON to work with JSON objects since version 5, so we can easily modify our API to return this (the response could also be an error object, which does NOT return a status field).

To return the status from our charge API call, we convert the procedure to a function so that it now looks like this

function charge_card (
    p_amount in NUMBER
  , p_currency in varchar2 default 'aud'
  , p_source in varchar2
  , p_description in varchar2
  , p_wallet_path in varchar2
  , p_wallet_password in varchar2
) 
return varchar2
as

    l_charge_resp CLOB;

begin
    
    l_charge_resp := 
        apex_web_service.make_rest_request(
            p_url => 'https://api.stripe.com/v1/charges'
          , p_http_method => 'POST'  
          , p_wallet_path => p_wallet_path
          , p_wallet_pwd => p_wallet_password
          , p_username => g_secret_token
          , p_parm_name => apex_util.string_to_table('amount:currency:source:description')
          , p_parm_value => apex_util.string_to_table(p_amount ||':'||p_currency||':'||p_source||':'||p_description)
        );
    
    apex_json.parse(l_charge_resp);
    
    return apex_json.get_varchar2(p_path => 'status');
    
end charge_card;

And updating our pay dynamic action to (with another page item to return the status into):

begin

    stripe_api.set_secret(:STRIPE_TOKEN);
    
    :P1_PMT_STATUS := 
        stripe_api.charge_card (
            p_amount => 2000
          , p_source => :P1_PMT_TOKEN
          , p_description => 'Charged from a D.A'
          , p_wallet_path => :WALLET_PATH
          , p_wallet_password => :WALLET_PASSWORD
        );

end;



Expanding from this going forward, you would more than likely want to return more than the status. You may want to also log the charges made locally (even though the info is all available from Stripe). This also needs better checking to cater for the situation of an error being returned instead of a Charge response.

Well, this series has just been one small component of what is possible with the Stripe API (I could be here all year if I set up examples of all components of the API). It makes it dead easy to integrate with - and if you are planning to offer same payment processing, I believe Stripe is a very good option!

2 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Wow! I have spent time looking for something like this, something explained with detail, step by step. You are the best, Trent. Thanks for share your knowledge and time with us. I really appreciate what you have done. Big hug!

    ReplyDelete