您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
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