PHP 백 엔 드 은 련 결제 및 환불 인 스 턴 스 코드
최근 에 은 련 결제 와 관련 환불(이 글 은 핸드폰 컨트롤 로 만 지불 하 는 것 을 전제 로)작업 을 하 게 되 었 습 니 다.다음은 그 동안 발생 한 문제 와 기본 절 차 를 차례대로 작성 할 것 입 니 다.그 전에 공식 사진 한 장 을 통 해 결제 에서 백 엔 드 직원 에 게 우리 가 해 야 할 일 들 을 알 아 보 겠 습 니 다.
이 를 통 해 알 수 있 듯 이 백 엔 드 는 여기 서 1.플랫폼 주문 생 성 을 책임 집 니 다.2.은 련 전 채널 플랫폼 주문 푸 시;3.tn 코드 를 되 돌려 전단 에 지불 합 니 다.4.프론트 데스크 알림 과 전 채널 플랫폼 의 비동기 알림 을 처리 합 니 다.
이 어 려 운 점 은 세 가지 가 있 습 니 다.주문 푸 시,비동기 통지 처리,주문 상태 조회 입 니 다.
공식 메 일 설명 을 통 해 관련 가방 을 다운로드 하고 백 엔 드 phop 코드 에 넣 습 니 다.그리고 SDK 의 readme.txt 파일 을 자세히 읽 고 다음 절 차 를 진행 합 니 다.
1.관련 매개 변수 설정
도 킹 과정 에서 sdk 의 assets 폴 더 에서 환경 설정 파일 및 인증 서 를 테스트 하고 sdk 폴 더 에 배치 하 며/sdk/SDKConfig.php 파일 이 올 바 르 게 읽 혔 음 을 설정 합 니 다 acpsdk.ini 프로필.
acpsdk.ini 파일 에 acpsdk.signCert.path,acpsdk.encrypter.path,acpsdk.rootCert.path,acpsdk.middleCert.path 네 파일 의 절대 주소(파일 경 로 를 사용자 정의 하면 됩 니 다)를 설정 합 니 다.
프로젝트 개발 과정 에서 시스템 이 다 르 거나 프로젝트 주소 가 다 르 기 때문에 인증서 의 절대 주소 등 오류 가 발생 할 수 있 습 니 다.특히 실제 생산 환경 에서 프로젝트 배치 파일 주소 가 다 르 기 쉬 우 므 로 개발 후 매번 업데이트 할 때마다 인증서 주 소 를 바 꿀 수 없습니다.SDK 의 SDK config.php 는 서로 다른 파일 주 소 를 호 환 했 습 니 다.여 기 는 또 클릭 해서 펼 쳐 보 세 요.
<?php
namespace com\unionpay\acp\sdk;;
include_once 'log.class.php';
include_once 'common.php';
class SDKConfig {
private static $_config = null;
public static function getSDKConfig(){
if (SDKConfig::$_config == null ) {
SDKConfig::$_config = new SDKConfig();
}
return SDKConfig::$_config;
}
private $frontTransUrl;
private $backTransUrl;
private $singleQueryUrl;
private $batchTransUrl;
private $fileTransUrl;
private $appTransUrl;
private $cardTransUrl;
private $jfFrontTransUrl;
private $jfBackTransUrl;
private $jfSingleQueryUrl;
private $jfCardTransUrl;
private $jfAppTransUrl;
private $qrcBackTransUrl;
private $qrcB2cIssBackTransUrl;
private $qrcB2cMerBackTransUrl;
private $signMethod;
private $version;
private $ifValidateCNName;
private $ifValidateRemoteCert;
private $signCertPath;
private $signCertPwd;
private $validateCertDir;
private $encryptCertPath;
private $rootCertPath;
private $middleCertPath;
private $frontUrl;
private $backUrl;
private $secureKey;
private $logFilePath;
private $logLevel;
function __construct(){
// acp_sdk.ini , 。
$configFilePath = dirname(__FILE__) . "/acp_sdk.ini";
$certsFilePath = dirname(dirname(__FILE__)) . "/certs/";
if(!file_exists($configFilePath)){
$logger = LogUtil::getLogger();
$logger->LogError(" , :[" . $configFilePath . "]. php 。");
return;
}
$ini_array = parse_ini_file($configFilePath, true);
$sdk_array = $ini_array["acpsdk"];
$this->frontTransUrl = array_key_exists("acpsdk.frontTransUrl", $sdk_array)?$sdk_array["acpsdk.frontTransUrl"] : null;
$this->backTransUrl = array_key_exists("acpsdk.backTransUrl", $sdk_array)?$sdk_array["acpsdk.backTransUrl"] : null;
$this->singleQueryUrl = array_key_exists("acpsdk.singleQueryUrl", $sdk_array)?$sdk_array["acpsdk.singleQueryUrl"] : null;
$this->batchTransUrl = array_key_exists("acpsdk.batchTransUrl", $sdk_array)?$sdk_array["acpsdk.batchTransUrl"] : null;
$this->fileTransUrl = array_key_exists("acpsdk.fileTransUrl", $sdk_array)?$sdk_array["acpsdk.fileTransUrl"] : null;
$this->appTransUrl = array_key_exists("acpsdk.appTransUrl", $sdk_array)?$sdk_array["acpsdk.appTransUrl"] : null;
$this->cardTransUrl = array_key_exists("acpsdk.cardTransUrl", $sdk_array)?$sdk_array["acpsdk.cardTransUrl"] : null;
$this->jfFrontTransUrl = array_key_exists("acpsdk.jfFrontTransUrl", $sdk_array)?$sdk_array["acpsdk.jfFrontTransUrl"] : null;
$this->jfBackTransUrl = array_key_exists("acpsdk.jfBackTransUrl", $sdk_array)?$sdk_array["acpsdk.jfBackTransUrl"] : null;
$this->jfSingleQueryUrl = array_key_exists("acpsdk.jfSingleQueryUrl", $sdk_array)?$sdk_array["acpsdk.jfSingleQueryUrl"] : null;
$this->jfCardTransUrl = array_key_exists("acpsdk.jfCardTransUrl", $sdk_array)?$sdk_array["acpsdk.jfCardTransUrl"] : null;
$this->jfAppTransUrl = array_key_exists("acpsdk.jfAppTransUrl", $sdk_array)?$sdk_array["acpsdk.jfAppTransUrl"] : null;
$this->qrcBackTransUrl = array_key_exists("acpsdk.qrcBackTransUrl", $sdk_array)?$sdk_array["acpsdk.qrcBackTransUrl"] : null;
$this->qrcB2cIssBackTransUrl = array_key_exists("acpsdk.qrcB2cIssBackTransUrl", $sdk_array)?$sdk_array["acpsdk.qrcB2cIssBackTransUrl"] : null;
$this->qrcB2cMerBackTransUrl = array_key_exists("acpsdk.qrcB2cMerBackTransUrl", $sdk_array)?$sdk_array["acpsdk.qrcB2cMerBackTransUrl"] : null;
$this->signMethod = array_key_exists("acpsdk.signMethod", $sdk_array)?$sdk_array["acpsdk.signMethod"] : null;
$this->version = array_key_exists("acpsdk.version", $sdk_array)?$sdk_array["acpsdk.version"] : null;
$this->ifValidateCNName = array_key_exists("acpsdk.ifValidateCNName", $sdk_array)?$sdk_array["acpsdk.ifValidateCNName"] : "true";
$this->ifValidateRemoteCert = array_key_exists("acpsdk.ifValidateRemoteCert", $sdk_array)?$sdk_array["acpsdk.ifValidateRemoteCert"] : "false";
$this->signCertPath = $certsFilePath . (array_key_exists("acpsdk.signCert.path", $sdk_array)?$sdk_array["acpsdk.signCert.path"]: null);
$this->signCertPwd = array_key_exists("acpsdk.signCert.pwd", $sdk_array)?$sdk_array["acpsdk.signCert.pwd"]: null;
$this->validateCertDir = array_key_exists("acpsdk.validateCert.dir", $sdk_array)? $sdk_array["acpsdk.validateCert.dir"]: null;
$this->encryptCertPath = $certsFilePath . (array_key_exists("acpsdk.encryptCert.path", $sdk_array)? $sdk_array["acpsdk.encryptCert.path"]: null);
$this->rootCertPath = $certsFilePath . (array_key_exists("acpsdk.rootCert.path", $sdk_array)? $sdk_array["acpsdk.rootCert.path"]: null);
$this->middleCertPath = $certsFilePath . (array_key_exists("acpsdk.middleCert.path", $sdk_array)?$sdk_array["acpsdk.middleCert.path"]: null);
$this->frontUrl = array_key_exists("acpsdk.frontUrl", $sdk_array)?$sdk_array["acpsdk.frontUrl"]: null;
$this->backUrl = array_key_exists("acpsdk.backUrl", $sdk_array)?$sdk_array["acpsdk.backUrl"]: null;
$this->secureKey = array_key_exists("acpsdk.secureKey", $sdk_array)?$sdk_array["acpsdk.secureKey"]: null;
$this->logFilePath = array_key_exists("acpsdk.log.file.path", $sdk_array)?$sdk_array["acpsdk.log.file.path"]: null;
$this->logLevel = array_key_exists("acpsdk.log.level", $sdk_array)?$sdk_array["acpsdk.log.level"]: null;
}
public function __get($property_name)
{
if(isset($this->$property_name))
{
return($this->$property_name);
}
else
{
return(NULL);
}
}
}
2.전 채널 상품 주문 푸 시관련 코드
use com\unionpay\acp\sdk\AcpService;
use com\unionpay\acp\sdk\LogUtil;
use com\unionpay\acp\sdk\SDKConfig;
/**
*
*
* @param $orders
* @param $orders_type
* @return array
*/
public function unionPay($orders, $orders_type = 0)
{
include_once dirname(dirname(dirname(__FILE__))) . '/Model/unionpay-sdk/sdk/acp_service.php';
$config = new SDKConfig();
$AcpService = new AcpService();
$log = LogUtil::getLogger();
$time = date('YmdHis', time());
$params = array(
//
'version' => $config->getSDKConfig()->version, //
'encoding' => 'utf-8', //
'txnType' => '01', //
'txnSubType' => '01', //
'bizType' => '000201', //
'frontUrl' => $config->getSDKConfig()->frontUrl, //
'backUrl' => $this->getURL('api_pay_unionpay_call_back'), //
'signMethod' => $config->getSDKConfig()->signMethod, //
'channelType' => '08', // ,07-PC,08-
'accessType' => '0', //
'currencyCode' => '156', // , 156
//TODO
'merId' => $this->getParameter('mer_id'), // ,
'orderId' => $orders["order_no"], // ,8-32 , “-” “_”
'txnTime' => $time, // , YYYYMMDDhhmmss,
'txnAmt' => $orders['total_price'] * 100, // ,
);
$AcpService->sign ( $params ); //
$url = $config->getSDKConfig()->appTransUrl;
$result_arr = $AcpService->post ($params, $url);
if(count($result_arr)<=0) { // 200 $log->LogInfo(' 200 ');
}
// $this->printResult ($url, $params, $result_arr ); //
if (!$AcpService->validate ($result_arr) ){
$log->LogInfo(' ');
}
if ($result_arr["respCode"] == "00"){
//
return array('txn_time'=>$time, 'tn'=>$result_arr["tn"]);
// echo " tn , tn 。
";
// echo " demo tn, tn, ,【 tn】。
";
} else {
//
return array('txn_time'=>$time, 'tn'=>0);
//echo " :" . $result_arr["respMsg"] . "。
";
}
}
txnTime 형식 이 잘못 전송 되 지 않도록 주의 하 십시오.테스트 환경 에서 문제 가 없 을 것 입 니 다.받 은 tn 을 앱 으로 되 돌려 지불 하면 됩 니 다.3.비동기 알림 처리 및 주문 거래 상태 조회
이 단 계 는 은 련 거래 의 성공 정 보 를 처리 하고 가능 한 한 리 셋 미 처리 로 인 한 문 제 를 피 하 는 데 주요 역할 을 한다.
먼저 비동기 통지 처 리 를 말 하고 이 절 차 는 주문 상태 수정 의 주요 근거 이다.실제 난점 이 없 으 면 관련 매개 변수 에 문제 가 없 음 을 보증 하면 된다.
/**
*
*
* @param Request $request
* @return array|Response
*/
public function unionPayCallBackAction(Request $request)
{
if ($request->get('type') == 1){// -
$query = $this->unionPayQuery($request, array(), 1);
return new JsonResponse($query);
}
require_once dirname(dirname(dirname(__FILE__))) . "/Model/unionpay-sdk/sdk/acp_service.php";
$log = LogUtil::getLogger();
$AcpService = new AcpService();
if ($request->request->has('signature') && $AcpService->validate($_POST)) {
$order_no = $request->request->get('orderId');
$respCode = $request->request->get('respCode');
$total = $request->request->get('txnAmt'); //
if ($respCode === '00' || $respCode === 'A6') {
$trade_no = $request->request->get('origQryId')?:'UN' . date('YmdHis', time()) . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
$this->dispose($order_no, $trade_no, 4);// -
}
} else {
if (!$request->request->has('signature')) {
$log->LogInfo(' ');
} else {
$log->LogInfo(' ');
}
}
exit;
}
주문 거래 상태 조회
do{// , queryID
sleep($number * 2);
$query = $this->unionPayQuery('', $orders);
$number += 1;
}while($query['errorCode'] != 0 || empty($query['result_arr']["queryId"]));
public function unionPayQuery($request, $orders)
{
require_once dirname(dirname(dirname(__FILE__))) . "/Model/unionpay-sdk/sdk/acp_service.php";
$config = new SDKConfig();
$AcpService = new AcpService();
$log = LogUtil::getLogger();
$params = array(
//
'version' => $config->getSDKConfig()->version, //
'encoding' => 'utf-8', //
'signMethod' => $config->getSDKConfig()->signMethod, //
'txnType' => '00', //
'txnSubType' => '00', //
'bizType' => '000000', //
'accessType' => '0', //
'channelType' => '07', //
//TODO
'orderId' => $orders['order_no'], // ,8-32 , “-” “_”
'merId' => $this->getParameter('mer_id'), // ,
'txnTime' => date('YmdHis', time()), // , YYYYMMDDhhmmss
);
$AcpService->sign ( $params ); //
$url = $config->getSDKConfig()->singleQueryUrl;
$result_arr = $AcpService->post ( $params, $url);
if(count($result_arr)<=0) { // 200 $log->LogInfo(' 200 ');
}
if (!$AcpService->validate ($result_arr) ){
$log->LogInfo(' ');
}
if ($result_arr["respCode"] == "00"){
if ($result_arr["origRespCode"] == "00"){
//
$trade_no = 'UN' . date('YmdHis', time()) . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
$this->dispose($orders['order_no'], $trade_no, 4);
$result = array('errorCode'=>0, 'message'=>' ', 'result_arr'=>$result_arr);
} else if ($result_arr["origRespCode"] == "03"
|| $result_arr["origRespCode"] == "04"
|| $result_arr["origRespCode"] == "05"){
//
$result = array('errorCode'=>2, 'message'=>' ', 'result_arr'=>$result_arr);
} else {
//
echo " :" . $result_arr["origRespMsg"] . "。
";
$result = array('errorCode'=>1, 'message'=>" :" . $result_arr["origRespMsg"] . ".", 'result_arr'=>$result_arr);
}
} else if ($result_arr["respCode"] == "03"
|| $result_arr["respCode"] == "04"
|| $result_arr["respCode"] == "05" ){
//
$result = array('errorCode'=>2, 'message'=>" , .", 'result_arr'=>$result_arr);
} else {
//
$result = array('errorCode'=>1, 'message'=>" :" . $result_arr["respMsg"] . ".", 'result_arr'=>$result_arr);
}
return $result;
}
여기까지 만 주문 라인 환불 이 없 으 면 완 료 됩 니 다.주문 환불 관련
public function refundUnionPay($orders)
{
require_once(dirname(dirname(__FILE__)) . "/Model/unionpay-sdk/sdk/acp_service.php");
set_time_limit(100);
$config = new SDKConfig();
$AcpService = new AcpService();
$log = LogUtil::getLogger();
$number = 0;
do{// , queryID
sleep($number * 2);
$query = $this->unionPayQuery('', $orders);
$number += 1;
}while($query['errorCode'] != 0 || empty($query['result_arr']["queryId"]));
if ($query['errorCode'] != 0) {
return array('errorCode'=>1, 'message'=>' , ');
}
$params = array(
//
'version' => $config->getSDKConfig()->version, //
'encoding' => 'utf-8', //
'signMethod' => $config->getSDKConfig()->signMethod, //
'txnType' => '04', //
'txnSubType' => '00', //
'bizType' => '000201', //
'accessType' => '0', //
'channelType' => '07', //
'backUrl' => $config->getSDKConfig()->backUrl, //
//TODO
'orderId' => "T" . $orders['order_no'], // ,8-32 , “-” “_”, , - T
'merId' => $this->getParameter('mer_id'), // ,
'origQryId' => $query['result_arr']["queryId"], // queryId,
'txnTime' => date('YmdHis', time()), // , YYYYMMDDhhmmss, ,
'txnAmt' => $orders['total_price'] * 100, // ,
);
$AcpService->sign ( $params ); //
$url = $config->getSDKConfig()->backTransUrl;
$result_arr = $AcpService->post ( $params, $url);
if(count($result_arr)<=0) { // 200 return array('errorCode'=>1, 'message'=>" .");
}
if (!$AcpService->validate ($result_arr) ){
return array('errorCode'=>1, 'message'=>" .");
}
if ($result_arr["respCode"] == "00"){
// , ,
return array('errorCode'=>0, 'message'=>" .");
} else if ($result_arr["respCode"] == "03"
|| $result_arr["respCode"] == "04"
|| $result_arr["respCode"] == "05" ){
//
return array('errorCode'=>1, 'message'=>" , .");
} else {
//
return array('errorCode'=>1, 'message'=>" :" . $result_arr["respMsg"] . ".");
}
}
반환 상태 값 에 따라 관련 조작 을 하면 됩 니 다.실제 논리 코드 는 스스로 실현 하 십시오.생산 환경 을 전환 하 다.
프로젝트 관계 진행 불가-추가 보충
미 완성 계속...
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
laravel에 yo에서 angularJs&coffeescript를 사용할 수 있도록 한다.먼저 yo 명령을 사용할 수 있어야하므로 아래에서 설치 global에 설치한 곳에서 laravel의 프로젝트 루트로 이동. 클라이언트 코드를 관리하는 디렉토리를 만들고 이동합니다. 클라이언트 환경 만들기 이것으로 히...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.