Success with Paypal, Stripe and Patreon on same checkout page

I’ve seen lots of reports of problems or questions about running paypal and stripe signup on same page. I wanted to report success, plus also adding my own support for patreon within that page. I’ve done some minor template customization with s2member but otherwise its stock with s2member pro.
You can see this working in production at https://www.stringclub.com/register/basic-membership/

The page even supports switching between monthly and yearly memberships. I didn’t really run into any major issues - I am running WordPress 5.0.1 with classic editor turned on. No issues with users subscribing, etc.

Thanks s2Member for the plugin.

1 Like

hey long time no see

1 Like

Nice work, Matt! Thanks for sharing your success! :smiley:

It is a problem if you load both forms together in the same page, but not if you switch between them, as you did.

Would you like to show others the code you used to achieve it? :slight_smile:

I’ll just dump the basics without the patreon stuff. One interesting thing to note is that both the stripe and paypal pro forms are loaded onto the page at the same time but only one is visible at a time. In order to not confuse the user if they switch processor after providing some of the field data, I have event handlers that listen for changes on fields in one form to update the equivalent field in the others. It feels like one form with some changes happening to it as you switch payment processor. Its fast because its just javascript and not going back to the server like changing the time period of membership renewal does.

Here is what I put into the WP page - text mode:

    <div class='tsc-membership-options'>
    <div class="card"><div class="card-block">
        <div class="card-title"><input type='radio' id='monthly' name='time' value='basic-monthly' /><label for='monthly'>Monthly</label></div>
        <div class="tsc-membership-price">
            <h2>$5/mo</h2>
        </div>
        <div>
            <ul>
                <li>Billed Monthly</li>
                <li>Cancel at anytime</li>
            </ul>
        </div>
    </div></div>
    <div class="card"><div class="card-block">
        <div class="card-title"><input type='radio' id='yearly' name='time' value='basic-yearly' /><label for='yearly'>Yearly</label></div>
        <div class="tsc-membership-price">
            <h2>$50/yr</h2>
        </div>
        <div>
            <ul>
                <li>Billed Yearly</li>
                <li>Best Value</li>
            </ul>
        </div>
    </div></div>
</div>
<div class="s2member-pro-paypal-form-section-title">Payment Processor</div>
<p>Use your PayPal account, or if you prefer another option, use your credit card directly via Stripe or control your StringClub membership via your Patreon donation.</p>

<div class='tsc-payment-processors'>
  <div><div class='tsc-processor-note'>&nbsp;</div>
    <button class="btn btn-green paypal" data-proc="paypal">Paypal</button>
  </div>
  <div><div class='tsc-processor-note'>Credit Card via</div>
    <button class="btn btn-outline-green stripe" data-proc="stripe">Stripe</button>
  </div>
  <div><div class='tsc-processor-note'>Control your membership via</div>
    <button class="btn btn-outline-green patreon" data-proc="patreon">Patreon</button>
  </div>
</div>
<div class='tsc-membership-form'>
<div class='tsc-paypal-form tsc-payment-form'>
    [s2Member-Pro-PayPal-Form level="1" custom="www.stringclub.com" accept="paypal" accpt_via_paypal="paypal"]
    [s2Member-Pro-PayPal-Form ccaps="" desc="$5 USD / Monthly (recurring charge, for ongoing access)" ps="paypal" lc="" cc="USD" dg="0" ns="1" ta="0" tp="0" tt="D" ra="5" rp="1" rt="M" rr="1" rrt="" rra="2" coupon="" accept_coupons="0" default_country_code="" captcha="0" success="/thank-you/?auth=1m" /]
    [s2Member-Pro-PayPal-Form ccaps="" desc="$50 USD / Yearly (recurring charge, for ongoing access)" ps="paypal" lc="" cc="USD" dg="0" ns="1" ta="0" tp="0" tt="D" ra="50" rp="1" rt="Y" rr="1" rrt="" rra="2" coupon="" accept_coupons="0" default_country_code="" captcha="0" success="/thank-you/?auth=1y" /]
    [/s2Member-Pro-PayPal-Form]
</div>
<div class='tsc-stripe-form tsc-payment-form' style='display:none'>
[s2Member-Pro-Stripe-Form level="1" custom="www.stringclub.com"]
[s2Member-Pro-Stripe-Form l ccaps="" desc="$5 USD / Monthly (recurring charge, for ongoing access)" cc="USD" ta="0" tp="0" tt="D" ra="5" rp="1" rt="M" rr="1" coupon="" accept_coupons="0" default_country_code="US" captcha="0" success="/thank-you/?auth=1m" /]
[s2Member-Pro-Stripe-Form l ccaps="" desc="$50 USD / Yearly (recurring charge, for ongoing access)" cc="USD" ta="0" tp="0" tt="D" ra="50" rp="1" rt="Y" rr="1" coupon="" accept_coupons="0" default_country_code="US" captcha="0" success="/thank-you/?auth=1y" /]
[/s2Member-Pro-Stripe-Form]
</div>
</div>

I use css to show hide stuff:

.tsc-membership-form {
    #s2member-pro-paypal-checkout-form-options-section,
    #s2member-pro-stripe-checkout-form-options-section {
		display: none !important;
	}
}

.tsc-payment-form {
    min-height:700px;
}

.tsc-payment-processors {
    display: flex;
    flex-flow: row wrap;

    .tsc-processor-note {
        font-size: small;
        margin-left: 15px;
    }

    >div:nth-child(2) {
        margin-left:25px;
    }
}
#s2member-pro-stripe-checkout-form-description-div {
    display:none;
}

@media (max-width:$colapse4) {
    .tsc-payment-processors {
        >div:first-child {
            width: 100%;
        }
        >div:nth-child(2) {
            margin-left:0;
        }
    }
}

I use JS to swap visibility based on interations with stuff from WP page content:

(function($) {
    var selectedCssName = "btn-green";
    var notSelectedCssName = "btn-outline-green";
    var active = "paypal";

    if($("#s2member-pro-paypal-checkout-options").val() == 2 || $("#s2member-pro-stripe-checkout-options").val() == 2) {
        $("#yearly").prop("checked", true);
    }
    else {
        $("#monthly").prop("checked", true);
    }
    var fieldSync = [
        ["#s2member-pro-stripe-checkout-first-name","#s2member-pro-paypal-checkout-first-name"],
        ["#s2member-pro-stripe-checkout-last-name","#s2member-pro-paypal-checkout-last-name"],
        ["#s2member-pro-stripe-checkout-email", "#s2member-pro-paypal-checkout-email"],
        ["#s2member-pro-stripe-checkout-username", "#s2member-pro-paypal-checkout-username", "#patreon_username"]

    ];

    fieldSync.forEach(function(flds) {
        var has3rd = flds.length > 2;
        if($(flds[0]).val()){
            $(flds[1]).val($(flds[0]).val());
        }
        else if($(flds[1]).val()){
            $(flds[0]).val($(flds[1]).val());
        }

        $(flds[0]).change(function() {
            $(flds[1]).val($(this).val());
            if(has3rd)
                $(flds[2]).val($(this).val());
        });
        $(flds[1]).change(function() {
            $(flds[0]).val($(this).val());
            if(has3rd)
                $(flds[2]).val($(this).val());
        });
        if(has3rd)
            $(flds[2]).change(function() {
                $(flds[0]).val($(this).val());
                $(flds[1]).val($(this).val());
            });

    });

    $("#monthly, #yearly").click(function() {
        var term = this.id;
        if(active == "paypal" || active == "stripe")
            $("#s2member-pro-" + active + "-checkout-options").val(term=="monthly"?1:2).change();   
    });

    $(".tsc-payment-processors").on("click", "button", function(evt) {
        $(".tsc-payment-processors button").removeClass(selectedCssName).addClass(notSelectedCssName);
        $(".tsc-payment-form").hide();
        var $this = $(this).removeClass(notSelectedCssName).addClass(selectedCssName);
        active = $this.data("proc");
        $(".tsc-"+ active +"-form").show();

    });
})(jQuery);
1 Like

Way to go Matt. the issue Im trying to bridge is using it in a price table. I could add 2 buttons per column one paypal and one for stripe, but with 7 levels, that is 14 buttons. Im using thrive themes and was going to try to do this in a lightbox, but their requirements for calling up the lightbox conflicts with ?s2p-option=