@@ -7,15 +7,17 @@ import (
77
88 "github.com/malwarebo/gopay/models"
99 "github.com/stripe/stripe-go/v82"
10- "github.com/stripe/stripe-go/v82/charge"
1110 "github.com/stripe/stripe-go/v82/dispute"
11+ "github.com/stripe/stripe-go/v82/paymentintent"
1212 "github.com/stripe/stripe-go/v82/plan"
1313 "github.com/stripe/stripe-go/v82/refund"
1414 "github.com/stripe/stripe-go/v82/subscription"
15+ "github.com/stripe/stripe-go/v82/webhook"
1516)
1617
1718type StripeProvider struct {
18- apiKey string
19+ apiKey string
20+ webhookSecret string
1921}
2022
2123func CreateStripeProvider (apiKey string ) * StripeProvider {
@@ -25,19 +27,29 @@ func CreateStripeProvider(apiKey string) *StripeProvider {
2527 }
2628}
2729
30+ func CreateStripeProviderWithWebhook (apiKey , webhookSecret string ) * StripeProvider {
31+ stripe .Key = apiKey
32+ return & StripeProvider {
33+ apiKey : apiKey ,
34+ webhookSecret : webhookSecret ,
35+ }
36+ }
37+
2838func (p * StripeProvider ) Charge (ctx context.Context , req * models.ChargeRequest ) (* models.ChargeResponse , error ) {
29- params := & stripe.ChargeParams {
30- Amount : stripe .Int64 (req .Amount ), // Amount is already in cents
39+ params := & stripe.PaymentIntentParams {
40+ Amount : stripe .Int64 (req .Amount ),
3141 Currency : stripe .String (req .Currency ),
3242 Description : stripe .String (req .Description ),
3343 Customer : stripe .String (req .CustomerID ),
3444 }
3545
36- // Set payment method
3746 if req .PaymentMethod != "" {
38- if err := params .SetSource (req .PaymentMethod ); err != nil {
39- return nil , fmt .Errorf ("failed to set payment method: %w" , err )
40- }
47+ params .PaymentMethod = stripe .String (req .PaymentMethod )
48+ params .Confirm = stripe .Bool (true )
49+ }
50+
51+ params .AutomaticPaymentMethods = & stripe.PaymentIntentAutomaticPaymentMethodsParams {
52+ Enabled : stripe .Bool (true ),
4153 }
4254
4355 if req .Metadata != nil {
@@ -49,29 +61,53 @@ func (p *StripeProvider) Charge(ctx context.Context, req *models.ChargeRequest)
4961 }
5062 }
5163
52- ch , err := charge .New (params )
64+ pi , err := paymentintent .New (params )
5365 if err != nil {
54- return nil , err
66+ return nil , fmt . Errorf ( "stripe payment intent creation failed: %w" , err )
5567 }
5668
5769 metadata := make (map [string ]interface {})
58- for k , v := range ch .Metadata {
70+ for k , v := range pi .Metadata {
5971 metadata [k ] = v
6072 }
6173
62- return & models.ChargeResponse {
63- ID : ch .ID ,
74+ status := models .PaymentStatusPending
75+ if pi .Status == stripe .PaymentIntentStatusSucceeded {
76+ status = models .PaymentStatusSuccess
77+ } else if pi .Status == stripe .PaymentIntentStatusRequiresAction {
78+ status = models .PaymentStatusPending
79+ } else if pi .Status == stripe .PaymentIntentStatusCanceled {
80+ status = models .PaymentStatusFailed
81+ }
82+
83+ paymentMethodID := ""
84+ if pi .PaymentMethod != nil {
85+ paymentMethodID = pi .PaymentMethod .ID
86+ }
87+
88+ response := & models.ChargeResponse {
89+ ID : pi .ID ,
6490 CustomerID : req .CustomerID ,
65- Amount : ch .Amount ,
66- Currency : string (ch .Currency ),
67- Status : models . PaymentStatusSuccess ,
68- PaymentMethod : ch . Source . ID ,
91+ Amount : pi .Amount ,
92+ Currency : string (pi .Currency ),
93+ Status : status ,
94+ PaymentMethod : paymentMethodID ,
6995 Description : req .Description ,
7096 ProviderName : "stripe" ,
71- ProviderChargeID : ch .ID ,
97+ ProviderChargeID : pi .ID ,
7298 Metadata : metadata ,
73- CreatedAt : time .Unix (ch .Created , 0 ),
74- }, nil
99+ CreatedAt : time .Unix (pi .Created , 0 ),
100+ }
101+
102+ if pi .NextAction != nil && pi .NextAction .Type == "redirect_to_url" {
103+ response .Metadata ["requires_action" ] = true
104+ response .Metadata ["next_action_type" ] = string (pi .NextAction .Type )
105+ if pi .NextAction .RedirectToURL != nil {
106+ response .Metadata ["redirect_url" ] = pi .NextAction .RedirectToURL .URL
107+ }
108+ }
109+
110+ return response , nil
75111}
76112
77113func (p * StripeProvider ) Refund (ctx context.Context , req * models.RefundRequest ) (* models.RefundResponse , error ) {
@@ -115,7 +151,15 @@ func (p *StripeProvider) Refund(ctx context.Context, req *models.RefundRequest)
115151}
116152
117153func (p * StripeProvider ) ValidateWebhookSignature (payload []byte , signature string ) error {
118- // Implement webhook signature validation
154+ if p .webhookSecret == "" {
155+ return fmt .Errorf ("webhook secret not configured" )
156+ }
157+
158+ _ , err := webhook .ConstructEvent (payload , signature , p .webhookSecret )
159+ if err != nil {
160+ return fmt .Errorf ("webhook signature verification failed: %w" , err )
161+ }
162+
119163 return nil
120164}
121165func (p * StripeProvider ) CreateSubscription (ctx context.Context , req * models.CreateSubscriptionRequest ) (* models.Subscription , error ) {
0 commit comments