Subversion Repositories PEEPS

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#!/usr/bin/perl
2
 
3
# Redirect error messages to a log of my choosing. (it's annoying to filter for errors in the shared env)
4
#my $error_log_path = $ENV{SERVER_NAME} eq "volunteers.rollercon.com" ? "/home3/rollerco/logs/" : "/tmp/";
5
#close STDERR;
6
#open STDERR, '>>', $error_log_path.'vorc_error.log' or warn "Failed to open redirected logfile ($0): $!";
7
#warn "Redirecting errors to ${error_log_path}vorc_error.log";
8
 
9
use strict;
10
use PEEPS;
11
use CGI qw/param header start_html url redirect/;
12
use CGI::Cookie;
13
our $h = HTML::Tiny->new( mode => 'html' );
14
my $dbh = getRCDBH ();
4 - 15
$ENV{HTTPS} = 'ON' if $ENV{SERVER_NAME} =~ /^peeps/;
2 - 16
 
17
my $cookie_string = authenticate (1) || die;
18
my ($EML, $PWD, $LVL) = split /&/, $cookie_string;
19
my $user = $ORCUSER;
20
#my $activated = $ORCUSER->{access};
21
 
22
use DateTime;
23
my $dt = DateTime->today;
24
$dt =~ s/T00\:00\:00$//;
25
 
26
my ($eligible, $daysremaining);
27
$user->{policy} = isPersonCovered ($user->{id});
28
if ($user->{policy}) {
29
  $daysremaining = remainingPolicyDays ($user->{id}, $user->{policy});
30
  if ($daysremaining <= 90) {
31
    $eligible = "renew";
32
  }
33
} else {
34
  $eligible = "new";
35
}
36
 
37
if (!$eligible) {
38
  print header (-cookie=>CGI::Cookie->new(-name=>'PEEPSAUTH',-value=>"$cookie_string"));
39
  printRCHeader("Atttestation");
40
  print $h->close ("table");
41
  print $h->h2 ("Not Eligible for Renewal");
42
  print $h->div ({ style=>"max-width:450px;" }, "You're currently covered by policy $user->{policy}, which has $daysremaining days remaining. You can only renew within the last 90 days of your current policy.", "&nbsp;");
43
  print $h->button ({onclick => "window.location.href='/';"}, "Home");
44
  print $h->close ("BODY", "HTML");
45
  logit ($user->{id}, "Viewed Attestation page but wasn't eligible to renew.");
46
  exit;
47
}
48
 
49
my ($abandoned_checkout) = $dbh->selectrow_array ("select url from square_order where person_id = ? and status = ? order by created desc limit 1", undef, $user->{id}, "DRAFT");
50
if ($abandoned_checkout) {
51
  my $cgi = CGI->new();
52
  logit ($user->{id}, "Returned to abandoned checkout.");
53
  print $cgi->redirect ($abandoned_checkout);
54
  exit;
55
}
56
 
57
my $terms;
58
foreach (1..8) {
59
  $terms++ if param ("Term".$_);
60
}
61
my $esig = param ("esignature") // "";
62
 
63
if ($terms == 8 and $esig =~ /^\w+$/) {
64
  # All of the checkboxes were accepted and an eSignature was entered.
65
  # Create the Square Checkout link and redirect the user there.
66
  logit ($user->{id}, "Submitted purchase attestation form with all terms accepted and esignature entered.");
67
  sendToSquare ($esig, $terms);
68
  exit;
69
}
70
 
71
print header (-cookie=>CGI::Cookie->new(-name=>'PEEPSAUTH',-value=>"$cookie_string"));
72
printRCHeader("Atttestation");
73
 
74
print $h->close ("table");
75
 
76
print $h->open ("form", { name => "Attestation", method => "post", action => url });
77
 
78
print $h->input ( { type => "hidden", name => "timezone", id => "TZFIELD", value => "" } );
79
 
80
print $h->div ({ class=>"error" }, "&nbsp;", "ERROR: You must agree to each term to continue.") if $terms and $terms < 8;
81
 
82
print $h->h2 ("Release and Waiver of Liability");
83
 
84
print $h->div ({ style=>"max-width:850px;" }, "RELEASE AND WAIVER OF LIABILITY, ASSUMPTION OF RISK, AND INDEMNITY AGREEMENT (\"Agreement\") IN CONSIDERATION of being permitted to participate this date, in any way, at any time, in Women’s Flat Track Roller Derby (\"Activity\"), I, for myself, my personal representatives, assigns, heirs, and next of kin:");
85
 
86
print $h->ol ({ style=>"max-width:850px;" }, [
87
  $h->li ("ACKNOWLEDGE, agree, and represent that I understand the nature of this Activity, and that I am qualified, in good health, and in proper physical condition to participate in such Activity. I further agree and warrant that if, at any time, I believe the conditions to be unsafe, I will immediately discontinue further participation in this Activity."),
88
  $h->li ("FULLY UNDERSTAND that: (a) THIS ACTIVITY INVOLVES RISKS AND DANGERS OF SERIOUS BODILY INJURY, INCLUDING PERMANENT DISABILITY, PARALYSIS, AND DEATH (\"Risks\"); (b) these Risks and dangers may be caused by my own actions or inactions, the actions or inactions of others participating in the Activity, the conditions in which the Activity takes place, or THE NEGLIGENCE OF THE \"RELEASEES\" NAMED BELOW; (c) there may be OTHER RISKS or SOCIAL AND ECONOMIC LOSSES either not known to me or not readily foreseeable at this time; and I FULLY ACCEPT AND ASSUME ALL SUCH RISKS AND ALL RESPONSIBILITY FOR LOSSES, COSTS, AND DAMAGES I incur as a result of my participation, in the Activity."),
89
  $h->li ("HEREBY RELEASE, DISCHARGE, AND COVENANT NOT TO SUE the sanctioning organization(s), their administrators, directors, agents, officers, members, volunteers, and employees, other participants, officials, rescue personnel, sponsors, advertisers, owners and lessees of Premises on which the Activity is conducted, (each of the forgoing shall be considered one of the RELEASEES herein) FROM ALL LIABILITY, CLAIMS, DEMANDS, LOSSES, OR DAMAGES ON MY ACCOUNT CAUSED, OR ALLEGED TO BE CAUSED, IN WHOLE OR IN PART BY THE NEGLIGENCE OF THE RELEASEES OR OTHERWISE, INCLUDING NEGLIGENT RESCUE OPERATIONS; AND I FURTHER AGREE that if, despite this RELEASE AND WAIVER OF LIABILITY, ASSUMPTION OF RISK, AND INDEMNITY AGREEMENT I, or anyone on my behalf, makes a claim against any of the RELEASEES, I WILL INDEMNIFY, SAVE, AND HOLD HARMLESS EACH OF THE RELEASEES from any litigation expenses, attorney fees, loss, liability, damage, or cost which may be incurred as the result of such claim."),
90
  ]);
91
 
92
print $h->div ({ style=>"max-width:850px;" }, "I ACKNOWLEDGE THAT I AM OVER THE AGE OF 18 YEARS, HAVE READ THIS AGREEMENT AND FULLY UNDERSTAND ITS TERMS, UNDERSTAND THAT I HAVE GIVEN UP SUBSTANTIAL RIGHTS BY SIGNING IT, HAVE SIGNED IT FREELY AND WITHOUT ANY INDUCEMENT OR ASSURANCE OF ANY NATURE, AND I INTEND IT TO BE A COMPLETE AND UNCONDITIONAL RELEASE OF ALL LIABILITY TO THE GREATEST EXTENT ALLOWED BY LAW AND AGREE THAT IF ANY PORTION OF THIS AGREEMENT IS HELD TO BE INVALID, THE BALANCE, NOTWITHSTANDING, SHALL CONTINUE IN FULL FORCE AND EFFECT.");
93
print $h->br;
94
print $h->div ({ style=>"max-width:850px;" }, [
95
  $h->div ({ class => "lisp0"}, [
96
    $h->div ({ class=>"liLeft" }, "I have read and agree with the WFTDA Release and Waiver of Liability, Assumption of Risk, and Indemnity Agreement *Click here to download the Release and Waiver of Liability form."),
97
    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term1" })])]),
98
  $h->h3 ("Accidental Medical"),
99
  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
100
    $h->div ({ class=>"liLeft" }, "I am 18 or older."),
101
    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term2" })])]),
102
  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
103
    $h->div ({ class=>"liLeft" }, "I am obtaining coverage for myself (I may not acquire coverage on behalf of someone else)."),
104
    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term3" })])]),
105
  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
106
    $h->div ({ class=>"liLeft" }, "My league has WFTDA Insurance. I understand I must obtain the same coverage as my league. If I am not affiliated with a league, I understand coverage is only valid when I skate with a WFTDA insured league."),
107
    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term4" })])]),
108
  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
109
    $h->div ({ class=>"liLeft" }, "I understand in order for insurance coverage to be in effect, I must adhere to the applicable Risk Management Guidelines and/or rules for the activity in which I am participating. Failure to do so will result in denial of claims and may result in revocation of coverage."),
110
    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term5" })])]),
111
  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
112
    $h->div ({ class=>"liLeft" }, "I understand if I am injured, I am responsible to submit an injury report, and must do so within 14 days of the date of my injury. I can request injury reports from insurance\@wftda.com. My league may assist me with this, but ultimately, it is my responsibility. Failure to submit an injury report within the allowable grace period will result in the denial of my claim."),
113
    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term6" })])]),
114
  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
115
    $h->div ({ class=>"liLeft" }, "I understand coverage is non-refundable and non-transferable. Coverage only transfers to other WFTDA Insured leagues."),
116
    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term7" })])]),
117
  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
118
    $h->div ({ class=>"liLeft" }, "I understand reckless or negligent behavior that is outside of the confines of game-related contact, including fighting, punching, kicking, or intentional injury, that puts you or any participant at risk is not tolerated, and is grounds for immediate termination of coverage."),
119
    $h->div ({ class=>"liRight" }, ["I Agree. ", $h->input ({ type => "checkbox", class => "attest", name => "Term8" })])]),
120
  $h->div ({ class => "lisp0", style=>"margin-bottom:1em"}, [
121
    $h->div ({ class=>"liLeft" }, "Electronic Signature:&nbsp;&nbsp;".$h->input ({ type => "text", name => "esignature", value => "<enter civil name>", onFocus => "this.value = '';"})),
122
    $h->div ({ class=>"liRight" }, $h->input ({ type => "submit", id=>"submitButton", disabled=>[], onClick => "if (esignature.value == '' || esignature.value == '<enter civil name>') { return false; }" }))]),
123
 
124
]);
125
 
126
print<<javascript;
127
 
128
<script>
129
  document.addEventListener('DOMContentLoaded', function() {
130
    const checkboxes = document.querySelectorAll('.attest');
131
    const submitButton = document.getElementById('submitButton');
132
 
133
    function checkAllCheckboxes() {
134
        let allChecked = true;
135
        checkboxes.forEach(checkbox => {
136
            if (!checkbox.checked) {
137
                allChecked = false;
138
            }
139
        });
140
        submitButton.disabled = !allChecked;
141
    }
142
 
143
    checkboxes.forEach(checkbox => {
144
        checkbox.addEventListener('change', checkAllCheckboxes);
145
    });
146
 
147
    // Initial check when the page loads
148
    checkAllCheckboxes();
149
  });
150
 
151
  const hiddenField = document.getElementById('TZFIELD');
152
  hiddenField.value = Intl.DateTimeFormat().resolvedOptions().timeZone;
153
</script>
154
 
155
javascript
156
 
157
print $h->close ("form"), $h->close ("body"), $h->close ("html");
158
 
159
 
160
 
161
 
162
sub sendToSquare {
163
  my $esig = shift || return "ERROR: No Signature";
164
  my $terms = shift // 8;
165
  my $user_tz = param ("timezone") // 'America/Chicago';
166
 
167
  use REST::Client;
168
  use JSON;
169
  use Data::Dumper;
170
  use UUID::Tiny qw(create_UUID_as_string UUID_V4);
171
 
172
  my $uuid_v4_string = create_UUID_as_string(UUID_V4);
173
  my $policy = getPolicyByID (1);
174
 
175
  my $client = REST::Client->new();
176
  $client->setHost (getSetting ("SQUARE_API_HOST"));
177
 
178
  my $headers = {
179
    "Authorization" => 'Bearer '.getSetting ("SQUARE_AUTH_TOKEN"),
180
    "Square-Version" => "2025-10-16",
181
    "Content-Type" => "application/json",
182
    };
183
 
184
  my $body = {
185
    "idempotency_key" => "$uuid_v4_string",
186
    "checkout_options" => {
187
      "redirect_url"  => url ( -base => 1)."/confirmation",
188
      "enable_coupon" => JSON::false
189
    },
190
#    "quick_pay" => {
191
#      "name" => $policy->{name},
192
#      "price_money" => {
193
#        "amount" => $policy->{fee} * 100,
194
#        "currency" => "USD"
195
#      },
196
#      "location_id" => getSetting ("SQUARE_LOCATION_ID")
197
#    },
198
    "order" => {
199
    	"customer_id" => "$user->{id}",
200
      "location_id" => getSetting ("SQUARE_LOCATION_ID"),
201
      "discounts"   => isWFTDAMember ($user->{id}) ? [{
202
        "name"  => "WFTDA Member Discount",
203
        "scope" => "ORDER",
204
#        "type" => "FIXED_AMOUNT",
205
        "amount_money" => {
206
          "amount"   => getSetting ("WFTDA_MEMBER_DISCOUNT") * 100,
207
          "currency" => "USD"
208
        }
209
      }] : [],
210
      "line_items" => [{
211
        "name" => $policy->{name},
212
        "quantity" => "1",
213
        "base_price_money" => {
214
          "amount" => $policy->{fee} * 100,
215
          "currency" => "USD"
216
        },
217
      }]
218
    },
219
    "payment_note" => $user_tz
220
  };
221
  my $json_body = encode_json $body;
222
 
223
  $client->POST(
224
    '/v2/online-checkout/payment-links',
225
    $json_body,
226
    $headers
227
  );
228
  my $response = from_json($client->responseContent());
229
#  warn Dumper($response);
230
 
231
#  warn $response->{payment_link}->{url};
232
 
233
  $response->{payment_link}->{created_at} =~ s/T/ /;
234
  $response->{payment_link}->{created_at} =~ s/Z$//;
235
 
236
  $dbh->do ("insert into square_order
237
             (square_id, order_id, person_id, url, idempotency_key, created, user_ip, amount, status, attestation)
238
             values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", undef,
239
             $response->{payment_link}->{id},
240
             $response->{payment_link}->{order_id},
241
             $user->{id},
242
             $response->{payment_link}->{url},
243
             $uuid_v4_string,
244
             $response->{payment_link}->{created_at},
245
             $ENV{REMOTE_ADDR},
246
             $policy->{fee},
247
             $response->{related_resources}->{orders}->[0]->{state},
248
             $terms." + ".$esig
249
           ) unless !$response->{payment_link}->{id};
250
 
251
  my $cgi = CGI->new();
252
  logit ($user->{id}, "Redirected to Square for payment");
253
  print $cgi->redirect ($response->{payment_link}->{url});
254
 
255
  exit;
5 - 256
}