-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WeChat Pay intent confirmation and error handling #10442
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Significance: minor | ||
Type: add | ||
|
||
Add WeChat Pay response handling. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -142,7 +142,7 @@ export default class WCPayAPI { | |
*/ | ||
confirmIntent( redirectUrl, shouldSavePaymentMethod = false ) { | ||
const partials = redirectUrl.match( | ||
/#wcpay-confirm-(pi|si):(.+):(.+):(.+)$/ | ||
/#wcpay-confirm-(pi|si):(.+):(.+):(.+):(.+)$/ | ||
); | ||
|
||
if ( ! partials ) { | ||
|
@@ -153,7 +153,7 @@ export default class WCPayAPI { | |
let orderId = partials[ 2 ]; | ||
const clientSecret = partials[ 3 ]; | ||
const nonce = partials[ 4 ]; | ||
|
||
const paymentMethodType = partials[ 5 ]; | ||
const orderPayIndex = redirectUrl.indexOf( 'order-pay' ); | ||
const isOrderPage = orderPayIndex > -1; | ||
|
||
|
@@ -199,6 +199,18 @@ export default class WCPayAPI { | |
).confirmCardPayment( clientSecret ); | ||
} | ||
|
||
if ( paymentMethodType === 'wechat_pay' ) { | ||
const confirmPayment = await stripe.confirmWechatPayPayment( | ||
clientSecret, | ||
{ | ||
payment_method_options: { | ||
wechat_pay: { client: 'web' }, | ||
}, | ||
} | ||
); | ||
return confirmPayment; | ||
} | ||
|
||
// When not dealing with a setup intent or woopay we need to force an account | ||
// specific request in Stripe. | ||
const stripeWithForcedAccountRequest = await this.getStripe( true ); | ||
|
@@ -211,6 +223,20 @@ export default class WCPayAPI { | |
confirmPaymentOrSetup() | ||
// ToDo: Switch to an async function once it works with webpack. | ||
.then( ( result ) => { | ||
let paymentError = null; | ||
if ( result.paymentIntent?.last_payment_error ) { | ||
paymentError = { | ||
message: | ||
result.paymentIntent.last_payment_error.message, | ||
}; | ||
} | ||
// If a wallet iframe is closed, Stripe doesn't throw an error, but the intent status will be requires_action. | ||
if ( result.paymentIntent?.status === 'requires_action' ) { | ||
paymentError = { | ||
message: 'Payment requires additional action.', | ||
}; | ||
} | ||
|
||
const intentId = | ||
( result.paymentIntent && result.paymentIntent.id ) || | ||
( result.setupIntent && result.setupIntent.id ) || | ||
|
@@ -238,9 +264,15 @@ export default class WCPayAPI { | |
: 'false', | ||
} ); | ||
|
||
return [ ajaxCall, result.error ]; | ||
return [ ajaxCall, paymentError || result.error ]; | ||
} ) | ||
.then( ( [ verificationCall, originalError ] ) => { | ||
.then( ( res ) => { | ||
const [ | ||
verificationCall, | ||
paymentError, | ||
originalError, | ||
] = res; | ||
Comment on lines
+267
to
+274
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at the Promise chain, is there a reason for destructuring three elements while the returned array consists of two only? Does this code mean we effectively moved throwing the |
||
|
||
if ( originalError ) { | ||
throw originalError; | ||
} | ||
|
@@ -255,6 +287,10 @@ export default class WCPayAPI { | |
throw result.error; | ||
} | ||
|
||
if ( paymentError ) { | ||
throw paymentError; | ||
} | ||
|
||
Comment on lines
+290
to
+293
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This error is thrown after the ajax call to ensure the order status updates for failed orders. |
||
return result.return_url; | ||
} ); | ||
} ) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -180,7 +180,12 @@ public function update_order_status_from_intent( $order, $intent ) { | |
break; | ||
case Intent_Status::REQUIRES_ACTION: | ||
case Intent_Status::REQUIRES_PAYMENT_METHOD: | ||
$this->mark_payment_started( $order, $intent_data ); | ||
if ( ! empty( $intent_data['error'] ) ) { | ||
$this->unlock_order_payment( $order ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's necessary to unlock the order here due to the |
||
$this->mark_payment_failed( $order, $intent_data['intent_id'], $intent_data['intent_status'], $intent_data['charge_id'], $intent_data['error']['message'] ); | ||
} else { | ||
$this->mark_payment_started( $order, $intent_data ); | ||
} | ||
break; | ||
default: | ||
Logger::error( 'Uncaught payment intent status of ' . $intent_data['intent_status'] . ' passed for order id: ' . $order->get_id() ); | ||
|
@@ -2056,6 +2061,7 @@ private function get_intent_data( WC_Payments_API_Abstract_Intention $intent ): | |
if ( $intent instanceof WC_Payments_API_Payment_Intention ) { | ||
$charge = $intent->get_charge(); | ||
$intent_data['charge_id'] = $charge ? $charge->get_id() : null; | ||
$intent_data['error'] = $intent->get_last_payment_error(); | ||
} | ||
|
||
return $intent_data; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stripe docs suggest using
confirmWechatPayPayment
for confirmation, but the flow looks almost identical for me when usinghandleNextActions
. Almost, because there's an extra redirect from the third-party page upon authorization/failure when usinghandleNextActions
. The QR displays well with both.Do we know if there is a real difference in flow handling with
confirmWechatPayPayment
? Using the streamlined handleNextActions would simplify the implementation. It solely depends on the API, and I'm not sure if we've asked Stripe about this?