Bussing Payment System - SIMPLIFIED Proof of Concept
Overview
Minimal viable product with just the essentials to prove the concept works.
Part 1: Simplified Table Structure (1-2 Tables)
OPTION A: Single Table (Simplest)
Table Name: Bus Registration (bus_registration)
| Column Name | Data Type | Required | Notes |
|---|---|---|---|
| Registration ID | Auto-number | Yes | Primary key |
| Student Name | Text | Yes | |
| Parent Name | Text | Yes | |
| Yes | |||
| Phone | Phone | Yes | |
| Grade | Text | Yes | e.g., “5” or “K” |
| Amount | Currency | Yes | Default: $200 (or whatever fee) |
| Payment Status | Choice | Yes | Options: Pending, Paid, Failed |
| Stripe Payment ID | Text | No | Store payment_intent ID |
| Payment Date | Date and Time | No | When paid |
| Created On | Date and Time | Yes | Auto-populated |
That’s it! Everything in one table for POC.
OPTION B: Two Tables (Slightly Better)
Table 1: Bus Registration
| Column Name | Data Type | Required | Notes |
|---|---|---|---|
| Registration ID | Auto-number | Yes | Primary key |
| Student Name | Text | Yes | |
| Parent Name | Text | Yes | |
| Yes | |||
| Phone | Phone | Yes | |
| Grade | Text | Yes | |
| Amount | Currency | Yes | Default: $200 |
| Payment Status | Choice | Yes | Pending, Paid, Failed |
| Created On | Date and Time | Yes | Auto |
Table 2: Payment
| Column Name | Data Type | Required | Notes |
|---|---|---|---|
| Payment ID | Auto-number | Yes | Primary key |
| Bus Registration | Lookup | Yes | Link to registration |
| Stripe Payment ID | Text | Yes | payment_intent_xxx |
| Amount | Currency | Yes | |
| Status | Choice | Yes | Pending, Succeeded, Failed |
| Payment Date | Date and Time | No |
Part 2: Simplified Power Automate Flow
Single Flow: Registration + Payment
Trigger: When a Bus Registration record is created
Steps:
Initialize variable: Stripe Secret Key
- Name: stripeKey
- Type: String
- Value: sk_test_YOUR_KEY_HERE (get from Stripe)
Initialize variable: Amount in Cents
- Name: amountCents
- Type: Integer
- Value:
mul(triggerOutputs()?['body/cr123_amount'], 100) - (Multiplies $200 by 100 = 20000 cents)
HTTP - Create Stripe Payment Intent
- Method: POST
- URI:
https://api.stripe.com/v1/payment_intents - Headers:
Authorization: Bearer @{variables('stripeKey')} Content-Type: application/x-www-form-urlencoded - Body:
amount=@{variables('amountCents')}¤cy=usd&metadata[registration_id]=@{triggerOutputs()?['body/cr123_busregistrationid']}&metadata[student_name]=@{triggerOutputs()?['body/cr123_studentname']}&automatic_payment_methods[enabled]=true
Parse JSON (from Stripe response)
- Content:
body('HTTP') - Schema:
{ "type": "object", "properties": { "id": {"type": "string"}, "client_secret": {"type": "string"}, "amount": {"type": "integer"}, "status": {"type": "string"} } }
- Content:
Update Bus Registration record
- Set Stripe Payment ID =
body('Parse_JSON')?['id']
- Set Stripe Payment ID =
Send Email (Office 365 Outlook connector)
- To:
triggerOutputs()?['body/cr123_email'] - Subject: “Complete Your Bussing Payment”
- Body:
<p>Hi @{triggerOutputs()?['body/cr123_parentname']},</p> <p>Thanks for registering @{triggerOutputs()?['body/cr123_studentname']} for school bussing.</p> <p>Amount due: $@{triggerOutputs()?['body/cr123_amount']}</p> <p><a href="https://yourpowerpage.com/payment?session=@{body('Parse_JSON')?['client_secret']}">Click here to pay now</a></p> <p>Registration ID: @{triggerOutputs()?['body/cr123_busregistrationid']}</p>
- To:
That’s your core flow!
Part 3: Simple Power Pages Setup
Page 1: Registration Form (5 minutes to build)
- In Power Pages, create new page “Bus Registration”
- Add a Form component
- Connect to Bus Registration table
- Show fields: Student Name, Parent Name, Email, Phone, Grade
- Set Amount field to hidden with default value ($200)
- Set Payment Status to hidden with default value (Pending)
- Success redirect: Show thank you message
Page 2: Payment Page (Basic HTML + Stripe)
Create a simple page with this code:
<!DOCTYPE html>
<html>
<head>
<script src="https://js.stripe.com/v3/"></script>
<style>
#payment-form { max-width: 400px; margin: 50px auto; }
button { background: #5469d4; color: white; padding: 12px 24px;
border: none; border-radius: 4px; cursor: pointer; }
</style>
</head>
<body>
<div id="payment-form">
<h2>Complete Payment</h2>
<div id="payment-element"></div>
<button id="submit">Pay Now</button>
<div id="error-message"></div>
</div>
<script>
// Get client_secret from URL parameter
const urlParams = new URLSearchParams(window.location.search);
const clientSecret = urlParams.get('session');
const stripe = Stripe('pk_test_YOUR_PUBLISHABLE_KEY'); // Replace with your key
const options = { clientSecret: clientSecret };
const elements = stripe.elements(options);
const paymentElement = elements.create('payment');
paymentElement.mount('#payment-element');
document.getElementById('submit').addEventListener('click', async () => {
const {error} = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: 'https://yoursite.com/confirmation',
},
});
if (error) {
document.getElementById('error-message').textContent = error.message;
}
});
</script>
</body>
</html>
Part 4: Stripe Webhook (Optional for POC)
Simple webhook to update payment status:
Trigger: When HTTP request is received
Steps:
Parse JSON (webhook body)
Condition: Check event type
- If
body('Parse_JSON')?['type']equalspayment_intent.succeeded
- If
Get Registration
- Filter: Stripe Payment ID equals
body('Parse_JSON')?['data']?['object']?['id']
- Filter: Stripe Payment ID equals
Update Registration
- Payment Status = Paid
- Payment Date = utcNow()
Send confirmation email
- “Payment received! Your student is registered.”
Part 5: Quick Start Guide
Step 1: Create Table (5 min)
- Go to make.powerapps.com
- Click “Tables” → “New table”
- Name it “Bus Registration”
- Add the columns from Option A above
Step 2: Get Stripe Keys (5 min)
- Go to stripe.com/test
- Sign up (free)
- Get test keys:
- Publishable key: pk_test_…
- Secret key: sk_test_…
Step 3: Create Power Automate Flow (10 min)
- Create new cloud flow
- Trigger: When row is added (Bus Registration table)
- Copy the steps from Part 2 above
- Replace YOUR_KEY_HERE with your sk_test key
Step 4: Create Power Pages Form (5 min)
- Create new Power Pages site (or use existing)
- Add form connected to Bus Registration table
- Publish
Step 5: Test! (2 min)
- Submit registration form
- Check email for payment link
- Use test card: 4242 4242 4242 4242
- Verify status updates to “Paid”
Test Cards (Stripe Test Mode)
- Success: 4242 4242 4242 4242
- Decline: 4000 0000 0000 0002
- Requires 3D Secure: 4000 0025 0000 3155
Use any future expiry date and any 3-digit CVC.
What This POC Proves
✅ Parents can register online ✅ Payment requests are created automatically ✅ Stripe handles secure payment processing ✅ Payment status updates automatically ✅ Confirmation emails are sent ✅ All data stored in Dataverse
When You’re Ready to Expand
After POC is approved, add:
- Webhook for real-time updates
- Payment tracking table
- Admin dashboard
- Route assignment
- Refund handling
- Reporting
Estimated POC Cost
- Power Pages: Free trial (30 days) or ~$200/month
- Power Automate: Included in most M365 licenses, or $15/month
- Stripe: FREE in test mode, 2.9% + $0.30 in production
Total to test: $0 (using trials)
POC Success Metrics
Can you:
- Submit a registration in under 2 minutes?
- Receive payment email automatically?
- Complete payment with test card?
- See status change to “Paid”?
- Retrieve data from Dataverse?
If yes to all = POC SUCCESS! ✅
Next Steps After POC
- Demo to stakeholders
- Get feedback on user experience
- Add webhook for real-time updates
- Expand to 2-3 table design
- Add admin reporting
- Switch to production Stripe keys
- Go live!
Quick Troubleshooting
Flow doesn’t trigger:
- Check table permissions
- Verify flow is turned ON
- Check flow run history
Payment fails:
- Verify Stripe key is correct (sk_test_…)
- Check amount is in cents
- Use valid test card
Email doesn’t send:
- Connect Office 365 Outlook
- Check email address is valid
- Look in spam folder
Need help with any specific step? Let me know!