您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
php项目集成stripe pay支付(v3)阿拉伯联合酋长国(阿联酋)支付
发布时间:2023-10-29 15:03:09编辑:雪饮阅读()
-
首先这里使用到的checkout.css主要是来源于
https://stripe.com/docs/payments/quickstart
这个示例的。
那么用到的stripe_public_key是由php后端返回的。
当然我这里是集成到项目里面了,所以由后端返回的,实际上,你也可以在stripe pay账户后台找到,分为正式模式和开发模式下的。
我这里暂时取的是开发模式下的,那么值是以pk_test开头的
而client_secret
则是以stripe pay后台的密钥(同样也是分正式模式和开发模式,那么这里暂时取的是开发模式的话就是sk_test开头的字符串)经过stripe pay的php的sdk进行生成的。
核心代码如:
$paymentIntent = $stripe->paymentIntents->create([
//aed货币最低面值不能低于2
//https://stripe.com/docs/currencies#%E6%9C%80%E4%BD%8E%E5%92%8C%E6%9C%80%E9%AB%98%E6%94%B6%E6%AC%BE%E9%87%91%E9%A2%9D
'amount' => $amount,
'currency' => 'aed',
// In the latest version of the API, specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default.
'automatic_payment_methods' => [
'enabled' => false,
],
'payment_method_types'=>[
'card'
],
'metadata'=>[
'order_id'=>$order_id,
'fid'=>$fid
]
]);
$client_secret=$paymentIntent->client_secret;
这里aed是阿拉伯联合酋长国的货币代号,在stripe pay中阿拉伯联合酋长国的货币支付最低不得低于2aed。
这里用的php的stripe pay的sdk的composer的依赖如
"stripe/stripe-php": "^12.2"那么最后整体的前面实现如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" name="viewport" content="width=device-width"> <title>Payment</title> <!-- 这里使用到的checkout.css主要是来源于https://stripe.com/docs/payments/quickstart这个示例的。 --> <link rel="stylesheet" href="/assets/css/checkout.css"> <style> body{ height: auto !important; } form{ width: 100% !important; } .stripe-country { display: none; } </style> <script src="/assets/js/jquery-1.10.2.min.js"></script> <script src="https://js.stripe.com/v3/"></script> <script src="/static/js/layer/layer.js"></script> <!--由于是在uniapp环境下,想要在支付完成后跳回app内部,所以这里就引用了这个js--> <script type="text/javascript" src="/assets/js/unpkg.com_@dcloudio_uni-webview-js@0.0.3_index.js"></script> <script> var stripe; var elements; var paymentElement; var type=new URLSearchParams(new URL(window.location.href).search).get("type"); var order_id=new URLSearchParams(new URL(window.location.href).search).get("order_id"); async function stripePaySubmit(){ var confirmPayment=await stripe.confirmPayment({ elements, confirmParams: { /* * return_url: * 确认支付成功后的跳转路径,我这里是跳转到这个路径后,然后用户自己再手动跳转到app内部,所以上面的/assets/js/unpkg.com_@dcloudio_uni-webview-js@0.0.3_index.js这个页面没有用到 * 不过先前版本我的支付成功后跳转路径也是当前页面,所以先前版本用到了 *payment_method_data: * 由于这个checkout的方式,其实默认会将国家下拉的选择也给你展示出来,以及邮政编码也展示出来 * 虽然country不用下拉选择也可以,以及邮政编码不用选择也可以 * 但是我这次是对接阿拉伯联合酋长国的支付,简称阿联酋的支付 * 所以国家这里我直接预选好,不想让用户选择(感觉怪怪的) * 所以国家就通过payment_method_data.billing_details.address.country指定好国家代号 * 那么邮政编码也是类似的,我暂时也不想让用户填写,所以就通过payment_method_data.billing_details.address.postal_code指定好邮政编码 * 此时国家下拉就会消失了,邮政编码输入框也会消失了 * */ return_url:document.location.protocol+'//'+document.domain+'/common/StripePay/paymentCompletion?type='+type+"&order_id="+order_id, payment_method_data:{ billing_details:{ address:{ //United Arab Emirates country:'AE', postal_code:'' } } } }, }); //针对确认支付过程中,是否遇到错误消息进行相应的页面上的处理 var error =confirmPayment.error; console.log("error",error); if (error.type === "card_error" || error.type === "validation_error") { layer.msg(error.message,{icon:0}); $("#submit").attr("disabled",false); } if(error.type=="invalid_request_error" && error.code=="payment_intent_unexpected_state" && error.payment_intent.status=="succeeded"){ $("#submit").attr("disabled",false); layer.msg("The order has been paid",{icon:0}); } else { layer.msg("An unexpected error occurred.",{icon:0}); console.log("error.message",error.message); $("#submit").attr("disabled",false); } } async function stripePay(){ stripe = Stripe('{$stripe_public_key}'); var client_secret=new URLSearchParams(new URL(window.location.href).search).get("client_secret"); if(client_secret=="" || client_secret==null){ return; } /* * appearance:定义这里checkout的整体风格,具体可以参考 * https://stripe.com/docs/elements/appearance-api?platform=web * */ const appearance = {}; /* * options: * 支付元素相关布局配置,具体参考 * https://stripe.com/docs/js/elements_object/create_payment_element * fields.billingDetails.address.country与fields.billingDetails.address.postalCode配置为never表示 * 不显示国家下拉以及不显示邮政编码的输入框 * 那么不显示国家下拉,则stripe pay就要求确认支付时候自己填入payment_method_data.billing_details.address.country * 同样的不显示邮政编码的时候,则stripe pay就要求确认支付的时候自己填入payment_method_data.billing_details.address.postal_code * */ const options = { layout: { type: 'accordion', defaultCollapsed: false, radios: false, spacedAccordionItems: true }, fields:{ billingDetails:{ address:{ country:'never', postalCode:'never' } } } }; elements = stripe.elements({ clientSecret:client_secret, appearance:appearance, //指定这里checkout中元素的默认语言,虽然我对接阿拉伯联合酋长国的支付,但是这里界面上还是希望显示的是英文,而不是阿拉伯语 locale:'en' }); //整个支付元素挂载 paymentElement = elements.create('payment', options); paymentElement.mount('#payment-element'); $("#submit").show(); paymentElement.on('change', function(event) { console.log("支付元素事件",event); if (event.complete) { console.log("enable payment button"); } }); } $(function(){ stripePay(); //监听付款提交按钮 $("#submit").click(function(){ $("#submit").attr("disabled",true); stripePaySubmit(); }); }) </script> </head> <body> <form> <div id="payment-element"></div> <button type="button" id="submit" style="display: none;" class="btn btn-default btn-success"> <div class="spinner hidden" id="spinner"></div> <span id="button-text">Pay now</span> </button> </form> </body> </html>那么关于最后的支付成功回调,如果说你想要在本地环境非公网环境也能收到,则是可以通过stripe pay cli工具来搭配使用。
参考如:
https://stripe.com/docs/payments/handling-payment-events
回调处理示例如:
StripePayCallBackController.php
<?php // +---------------------------------------------------------------------- // | ThinkCMF [ WE CAN DO IT MORE SIMPLE ] // +---------------------------------------------------------------------- // | Copyright (c) 2013-present http://www.thinkcmf.com All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: 小夏 < 449134904@qq.com> // +---------------------------------------------------------------------- namespace app\common\controller; use app\common\model\main\FarmModel; use app\common\model\main\FarmPaymentMethodModel; use app\common\model\main\OrderModel; use cmf\controller\BaseController; use think\facade\Log; class StripePayCallBackController extends BaseController { public function index() { $payload=file_get_contents('php://input'); $sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE']; $endpoint_secret = 'whsec_...'; $event = null; $order_id=null; $order=null; try { $payloadArr= json_decode($payload, true); if(!isset($payloadArr["data"]["object"]["metadata"]["order_id"])){ http_response_code(400); echo json_encode(['Error parsing payload: ' => 46]); Log::write('StripePayCallBackController错误:46','notice'); exit(); } $order_id=$payloadArr["data"]["object"]["metadata"]["order_id"]; $order=OrderModel::where("id",$order_id)->find(); $fid=$order["fid"]; $farm=FarmModel::where("id",$fid)->find(); $paymentMethod=FarmPaymentMethodModel::where("id",$farm["payment_method_id"])->find(); if($paymentMethod){ $paymentMethod=$paymentMethod->toArray(); } Log::write('StripePayCallBackController:64:'.var_export($paymentMethod,true),'notice'); $endpoint_secret=$paymentMethod["stripe_webhook_secret"]; \Stripe\Stripe::setApiKey($paymentMethod["stripe_secret_key"]); $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $endpoint_secret ); } catch(\UnexpectedValueException $e) { // Invalid payload http_response_code(400); Log::write('StripePayCallBackController错误:65','notice'); echo json_encode(['Error parsing payload: ' => $e->getMessage()]); exit(); } catch(\Stripe\Exception\SignatureVerificationException $e) { // Invalid signature http_response_code(400); Log::write('StripePayCallBackController错误:71','notice'); echo json_encode(['Error verifying webhook signature: ' => $e->getMessage()]); exit(); } if($event->type=="payment_intent.succeeded"){ try { $OrderModel=new OrderModel(); $OrderModel->order_handle($order_id); }catch (\Exception $e){ Log::write('StripePayCallBackController错误:143','notice'); http_response_code(400); exit(); } } http_response_code(200); } }这里用到的stripe_webhook_secret,也是在stripe pay的账户后台建立end point端点,例如我这里是建立的payment_intent.succeeded的断点后就可以看到该端点的webhook的secret了。
那么最后的示例效果如
国外支付呢一般主要是银行卡支付,所以这里默认我也只是配置了银行卡支付。
当然除了这些编码工作以外,你还需要在stripe pay后台添加银行卡支付的支付方式才行。
这里如果你要测试支付,则默认开发模式下可用:
测试银行卡
交互测试时,使用一个卡号,例如 4242 4242 4242 4242。在管理平台或任意支付表单中输入卡号。
使用有效的未来日期,例如 12/34。
使用任意三位数 CVC(American Express 卡为四位)。
其他表单字段可以使用任意值。
关键字词:stripe,pay,阿拉伯,阿联酋,阿拉伯联合酋长国,v3,php