Takeaway:
As a small webmaster or developer, the website needs access to the payment function to realize the site’s cash profit, generally there are the following schemes:
1. Third-party payment platform: As of November 23, 2020, there are 237 companies with third-party payment licenses in China. Since 2015, 34 third-party payment companies have had their payment licenses canceled. It is not easy to apply for third-party payment, which requires enterprise qualification to open and strict review.
TOP5 third-party payment companies in 2020
ranking | Third-party payment Company | APP or payment brand |
1 | Tenpay Payment Technology Co., LTD | Tenpay and wechat Pay |
2 | Alipay (China) Network Technology Co. LTD | Alipay |
3 | China Union Pay Co. LTD | Unionpay business |
4 | Ping an Fu Technology Service Co., LTD | This wallet |
5 | Fast Money Payment Clearing Information Co., LTD | quick |
6 | Suning Consumer Finance Co. LTD | Suning Finance (Suning Pay) |
7 | Linkage advantage E-commerce Co., LTD | Linkage advantage |
8 | Jingdong Digital Technology Holding Co. LTD | Jingdong pay |
9 | Lakala Payments Co., LTD | La cara |
10 | Tonglian Payment Network Service Co. LTD | Tonly pay |
11 | Yibao Payment Co., LTD | Yeepay |
12 | Xunfu Information Technology Co., LTD | Ring fast payment |
13 | Beijing Duxiaoman Payment Technology Co. LTD | Pay when you are full |
14 | Tianyi Electronic Commerce Co. LTD | Wing to pay |
15 | China Mobile Electronic Commerce Co., LTD | And the package to pay |
16 | E-bank Online (Beijing) Technology Co., LTD | Net silver online |
17 | Unicom Payment Co. LTD | Unicom payment |
18 | Shanghai Shengpay Electronic Payment Service Co. LTD | Sheng tenpay |
19 | Beijing Haike Rongtong Payment Service Co. LTD | Heiko accommodation |
20 | Yi Sheng Payment Co., LTD | Easy pay |
21 | Travel payment Co. LTD | The accompanying pay Plus |
22 | Hainan Island One-card Payment Network Co. LTD | Hainan One-card |
23 | National Fubao Information Technology Co., LTD | The FuBao |
24 | Yinsheng Payment Service Co. LTD | Silver sheng pay |
25 | Netease Treasure Co., LTD | Netease treasure |
26 | Lianlian Yintong Electronic Payment Co., LTD | All payment |
27 | Beijing Qianbagbao Payment Technology Co. LTD | Purse treasure |
28 | Alipay Network Technology (Shanghai) Co., LTD | Pay treasure |
29 | Shande Payment Network Service Development Co., LTD | Chinese fir DE payment, |
30 | Zhifu Electronic Payment Co., LTD | Wisdom pay Dinpay |
31 | China Pay Payment Technology Co., LTD | The pay pay |
32 | Shanghai Paypass Information Service Co. LTD | Pay through |
33 | Remittance world Limited | Remittance world |
34 | Ubs Credit Payment Technology Co., LTD | Ubs’s letter |
35 | Beijing Sina Payment Technology Co. LTD | Sina pays |
36 | Shanghai Fuyou Payment Service Co. LTD | Rich company pay |
37 | Ez-pay Technology (Beijing) Co., LTD | Credit easy payment |
38 | Express Payment Services LTD | Quick links |
39 | Cicc Payment Co., LTD | Cicc’s pay |
40 | Guangzhou Convergence Payment Electronic Technology Co., LTD | Together to pay |
41 | Deshi Co., LTD | Have to blackstone |
42 | Information electronic Payment Co., LTD | Information and letters |
43 | E-link Payment Co., LTD | Easy union pay |
44 | Shanghai Oukebei Network Technology Co., LTD | Allpay |
45 | Unipay (Zhejiang) Information Technology Co., LTD | Optimal money to pay |
46 | Sichuan Shangtong Industrial Co., LTD | Shang tong |
47 | Kayou Payment Service Co., LTD | Friends and card payment |
48 | Chongqing Yijifu Technology Co., LTD | Yi extremely pay |
49 | Double Dry Network Payment Co., LTD | Double do pay |
50 | Xinsheng Payment Co., LTD | New payment |
2. Fourth Party Payment (aggregate payment) : The fourth Party payment is relative to the third party. As an expansion of the third-party payment platform services, the third party payment is between the bank and the merchant, while the fourth Party payment is between the third party payment and the merchant, without the restriction of payment license. The third party payment provides a fund clearing channel, while the fourth Party Payment provides a variety of derivative services on the basis of payment. As a middleman connecting third-party payment institutions and merchants, aggregative payment is only the bearer of information transfer and merchant operation in the payment link. It is engaged in “payment service” other than “payment, settlement and clearing” service, and does not provide a channel for capital settlement. The payment and settlement department of the People’s Bank of China about violations “aggregate payment” service clean-up work notice, will be paid for aggregation in “single outsourcing institution”, the aggregate pay scratched four clear red line, namely “four not”, one of which is “shall not handle any form of specially engaged settlement funds, engaged in or in disguised forms specially engaged capital settlement”. In other words, aggregate Payment companies are only technical service organizations providing third-party payment channels for merchants, and cannot deposit funds, let alone provide payment and capital settlement for merchants. Aggregator payment itself is not illegal, but if the aggregator payment platform is engaged in settlement business, it will intercept the funds of merchants and form the so-called “capital pool”, which is illegal and risky. It is precisely because of the existence of risks, so many small aggregation payment platforms without the approval of the relevant national authorities are doing a period of time to run away, just to avoid this risk. We should choose the fourth party aggregation payment platform, must be careful!
3. Personal free signing system: Use personal Alipay or wechat payment code, and then Android monitor APP payment notification to realize payment. In essence, it adopts the strategy of hanging up and monitoring, but it is aimed at the payment notification messages of mobile terminal Alipay or wechat. It costs a lot and is difficult to configure. It takes 24 hours to hang up an Android phone, which is not free.
For individual developers, these solutions are either unenterprise-qualified, too cumbersome, or too expensive. Is there a better solution? The answer is: of course have, that is pay treasure face to face pay, let us discuss step by step below.
Application conditions for face-to-face payment:
1. Supported account type: real-name verified personal/corporate Alipay account
2. Materials submitted for signing application:
1) Photos of business premises
A. For business premises with shop doors, door photos shall be provided;
B. For business premises without shop doors, internal or scene photos shall be provided
Reminder: If the business scene photos are not submitted in a standard manner, the payment will be limited. The business needs to complete the information within 30 days, otherwise the normal payment will be affected.
2) Business license with the same name as real-name alipay account holder (i.e. the name of legal representative of the business license is the same as the name of alipay account holder)
Reminder: if the business license of the same name is not provided, it can be used for a long time but the merchant has a limit on payment.
3. The rate
The service name | rate | The service period |
---|---|---|
A single rate | 0.6% | 1 year |
Description:
- To apply for payment in person, it is very easy. You just need to find a shop front photo, take one outside, or search the website.
- The business license is optional. If you do not upload it, you are limited to a single payment of less than 1000 and a single day of payment of less than 5W. For small websites, this amount is enough.
Supplement:
If your Alipay account is too risky when you apply, switch to another account. The rule system of pay treasure can detect the trade in the near future of your account commonly, see whether there is a risk, the pay treasure account that registers newly, cannot apply for face to face to pay commonly.
Face-to-face payment application process:
1, click here to enter, login alipay account, and then click “Open now”.
2. Fill in the basic information. The red asterisk is mandatory:
- Management content chooses department store retail → supermarket → supermarket, perhaps choose other, the proposal does not choose platform kind, pay kind, game kind, these review is strict, do not have enterprise qualification and telecommunication add value permit to be passed not.
- Business license can not upload.
- Shop signs, is the photo of the store, you can go outside to take a picture, but also baidu search.
- Acceptance notification will be received more than 10 minutes after the application is submitted.
Face-to-face payment development process:
First, preparation
1. To apply for a successful developer, go to developers.alipay.com/.
2. After successful application of face-to-face payment, you can see an application of “Application 2.0 signing 20210203*********” added to my application list in ant Financial open platform webpage & mobile application
Configure public and private keys to be paid in person
1, use “pay treasure to open platform development assistant” generating RSA key (including application public key and private key), the official tutorial address: opendocs.alipay.com/open/291/10…
Online key generation:Miniu.alipay.com/keytool/cre…
2. Click to enter application 2.0 signing 20210203*********
3. On the left menu bar, set the public key in “Application Information” and set “Interface Signature Mode”.
4. Copy the generated application public key and save the Settings
3. Official API parameters
Gateway address:openapi.alipay.com/gateway.do
1. Common request parameters:
parameter | type | If required | The maximum length | describe |
---|---|---|---|---|
app_id | String | is | 32 | The app ID assigned to the developer by Alipay |
method | String | is | 128 | The name of the interface |
format | String | no | 40 | Only support JSON |
charset | String | is | 10 | The encoding format used in the request, such as UTF-8, GBK, GB2312, etc |
sign_type | String | is | 10 | Type of the signature algorithm used by the merchant to generate signature strings. Currently, RSA is supported |
sign | String | is | 256 | Signature string for merchant request parameters, see detailsThe signature |
timestamp | String | is | 19 | Time when the request is sent in the format “YYYY-MM-DD HH: MM: SS” |
version | String | is | 3 | The interface version of the call, fixed at: 1.0 |
notify_url | String | no | 256 | Alipay server actively notifies the merchant server of the specified page HTTP/HTTPS path. |
app_auth_token | String | no | 40 | As shown in theApplication Authorization Overview |
biz_content | String | is | – | A collection of request parameters, of unlimited length, in which all request parameters except public parameters must be passed, refer to the quick access documentation for each product |
2. Request parameters:
parameter | type | If required | The maximum length | describe |
---|---|---|---|---|
out_trade_no | String | Must be | 64 | The merchant order number contains no more than 64 characters and can contain letters, digits, and underscores (_). Ensure that there is no duplication at the merchant end |
scene | String | Must be | 32 | Payment scenario Barcode payment, value: bar_code Acoustic payment, value: wave_code |
auth_code | String | Must be | 32 | Payment authorization code |
seller_id | String | optional | 28 | If the value is empty, it is the alipay user ID corresponding to the merchant’s signed account by default |
total_amount | Price | optional | 11 | Total order amount, unit: YUAN |
discountable_amount | Price | optional | 11 | The amount involved in the preferential calculation, in yuan |
undiscountable_amount | Price | optional | 11 | The amount not participating in the preferential calculation, the unit is yuan |
subject | String | Must be | 256 | Order the title |
body | String | optional | 128 | Order to describe |
goods_detail | GoodsDetail [] | optional | – | The product list information contained in the order is in Json format. For other descriptions, see product details |
operator_id | String | optional | 28 | Merchant Operator Number |
store_id | String | optional | 32 | Merchant Store No. |
terminal_id | String | optional | 32 | Merchant equipment terminal number |
alipay_store_id | String | optional | 32 | The store number of Alipay |
extend_params | ExtendParams | optional | – | Service extension parameters |
timeout_express | String | optional | 6 | The latest payment time allowed for this order will close the transaction. |
royalty_info | RoyaltyInfo | optional | – | Describes the account distribution information in Json format. For other descriptions, see The account distribution description |
sub_merchant | SubMerchant | optional | – | Secondary merchant information. Currently, this field is only used in specific scenarios of special banking institutions |
3. Public response parameters:
parameter | type | If required | The maximum length | describe |
---|---|---|---|---|
code | String | is | – | Gateway return code,See the documentation for |
msg | String | is | – | Gateway return code description,See the documentation for |
sub_code | String | no | – | Business return code,See the documentation for |
sub_msg | String | no | – | Service return code description,See the documentation for |
sign | String | is | – | The signature,See the documentation for |
4. Response parameters
parameter | type | If required | The maximum length | describe |
---|---|---|---|---|
trade_no | String | mandatory | 64 | Alipay transaction number |
out_trade_no | String | mandatory | 64 | Merchant Order Number |
buyer_logon_id | String | mandatory | 100 | Buyer’s Alipay account |
total_amount | Price | mandatory | 11 | Transaction amount |
receipt_amount | String | mandatory | 11 | Paid-in amount |
buyer_pay_amount | Price | optional | 11 | The amount paid by the buyer |
point_amount | Price | optional | 11 | The amount of payment made by alipay |
invoice_amount | Price | optional | 11 | The amount of the transaction that can be invoiced to the user |
gmt_payment | Date | mandatory | 32 | Transaction payment time |
fund_bill_list | TradeFundBill [] | mandatory | – | The channel of funds used for transaction payment |
card_balance | Price | optional | 11 | Balance of alipay card |
store_name | String | optional | 512 | Name of the merchant store where the payment transaction occurs |
buyer_user_id | String | mandatory | 28 | The buyer’s user ID on Alipay |
discount_goods_detail | String | mandatory | – | This transaction is paid for by the single coupon discount merchandise information |
Three, sandbox test environment
If the face-to-face payment has not been successfully signed, you can first use the sandbox account to test, the method is as follows:
1, login pay treasure development platform openhome.alipay.com/platform/ho… , development services → RESEARCH and development services
2, Sandbox application, set RSA2(SHA256) key, the same as above set application public key.
3. Set up the application gateway for receiving alipay asynchronous notification
Fourth, code writing
You can pay the SDK examples download official face to face, the download link: opendocs.alipay.com/open/194/10…
I have a general look at the official example, involving more class files, for beginners or more complex, so I simplify it, you can refer to my Thinkphp framework code below.
1. Create a pay folder under extend and create an Alipay. PHP class in the pay folder as follows:
namespace pay;
use \think\Db;
use app\common\model\Order as OrderModel;
/** * alipay payment class */
class Alipay {
// Whether to sandbox the environment
public $is_sandbox = true;
// Sandbox address
private $sandurl = 'https://openapi.alipaydev.com/gateway.do';
// Official address
private $apiurl = 'https://openapi.alipay.com/gateway.do';
// Gateway address
private $gateway;
// Alipay APPID
private $appid;
// Apply the private key
private $rsaPrivateKey = 'Private key set up by merchant';
// Alipay public key
private $alipayPublicKey= 'Public key automatically generated by Alipay';
private $charset = 'utf-8';
public function setAppid($appid)
{
$this->appid = $appid;
}
public function setRsaPrivateKey($rsaPrivateKey)
{
$this->rsaPrivateKey = $rsaPrivateKey;
}
public function setAlipayPublicKey($alipayPublicKey)
{
$this->alipayPublicKey = $alipayPublicKey;
}
// constructor
public function __construct($account){
// If it is a sandbox test
if($this->is_sandbox){
$this->gateway = $this->sandurl;
$this->appid = '2021000117612368';
$this->rsaPrivateKey ='MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDF0Bwt0712ogHbqp245rlz6Rj7LePxxhO4HoIUZhmZS7OeC1muhLK44e9kznFGT6YvOE2 rasZT+EixPLifYqUML0Ecmxxvt3dr/WrAIIM941ODhjCaV+CDjZYNBZmsK+nPojFNWuyZCq9ygzX43XOjk3oTNbws5/tJdA4fzKIhlufuvpeGL5tgzoLKxUy 2oweVluIyqkhFZUs9/9vgiUwFVt/iPf4JREGJ56Vq1grOBd+ZGqrljCcx6mEOm7GGd0lcDw038L//MYICdAgLfmCF+aojkRm3qkcTt7bl0jYsYnAWqxkBvtp CWQzFKMbwVsqbOM5EUzle8csNuguXqZ3TAgMBAAECggEAQXoSacTluOgFT23ZSUPt7QUiRLo68mOLUW2fxxrIrGpXaR/+rnq0Ieh/clG3QvvIWWb8ppnwTgk oHqqnvfJMCY12sv5Q2lXTTMaUWEYqywh9M1LusZgW89Sg72yEIm5itVzNjvpiyIG182SlL9w1k9aUGNm3kPG0xuqIZlQ48n7IZSeDGg+5ic4J+U7PGaCV99Q 2zq7mkuIrbot+p478oFR7aM1/24OfxdJ1eh4FZZevwmLHpwqZEhecZFGrKx6/wlzDOhaiR7PgGcjH0/q6tiw6g5TCWfAzBDfFl/ZdRToNP6mOe57qt7jKhQz +2Lxz0qLNdNDacyTSYIkFg9cE0QKBgQD3AyFhrFk0VaTN2Xt6OAOEn1UIf1aBPenFQfV8+tIlbL5Io3VHHmycMuctW7c2BGkp7HF9OwcYGtURQdaBRCyKAYn W1nbZRgLHhkFC9rLyG04/yv6pN6/8EZ4bow7aUiCGoR/mV5GehiWTjb5/thCS+enaaalTdAfQBGZOl7VyGwKBgQDNArKycIbtXl2BEqcIqwW2nzv0RA8FhK7 LkRy1CFIAeZfr1O4FiSXM/3V/EuocISCwOLWRq5Qyx7mZoMZ4FSRlQFbo9LUmYtIXtKHekwYZEpxleXJOVudRRQa3GkMvWAd3s1MSCGQ44jHFc/vbap6fxfR /GWHupoMOvW4N06h+qQKBgAFzekG5oniFPEedTHVmWNbxnK1FGjv+Ih5vicKnMo7XubJxi2HUkuzD+8mvbT8a/YcqhWwn6Z3BopjMWzc9MEnLQoUJk38pQyD q7/01t81mTapgRei2lAkWDWi6J38u1lQUJDzVLNzSiuv3/DOB3U0PvMj0r/L2jokxTWyOxZkbAoGBAK8DuqHyxn0lrhVeYxJXTg1Vas1gvKItXzuRqjwx2i9 lnnhJ0tkO+CJFg3z0HL/e2BUYlIjDPUUMlDm+szAYfHWjs440OeGHQ2vRXM6yHOaSqMlIIHkYX2lV0CHIXcqxD870W9ptJ4IYN/0kwsHSB5DGYa+Pb7dYl1G iDa3oH1PhAoGBAPCSjFfXd45BPYDNL+4N9zS2wT5pjxlSo3Jrg3NKOqBZLS52ygZ6xeANXrG7lzitJ75prUS/JyXS83SM8au0vcO1Fko9BbW7MkuKFZH7FSp Olv5/PJQ6tI55TV7gGl8l4ND7V9OSdAMhEBQ/uT2gmddFoRTB14MeLIpe2iIVonan';
$this->alipayPublicKey = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs9AE75V+F242HcN/SlcGUxUNv3zGpXjai4u2ZMkOL1nolr4/v4BGEsE8tLaYq6lecG/of5taQ27 WbWXB5PMB3s6emesTEn5yvZPh/HqmKACHi7js+Dtu123J/z0DyCukMm1ZHJe7jT9VEU9w4gIdNi64VxdaRF3ZMT6DXnboUEegyRKGmJc58h+O30P/UYqdCW/ Gl+380o80e6Fs0rX33AixkNTRNgnQ3n2er1Nrqan/9sfUCnqqxgpc1+GTT+vyn3x4Xwvch2pRIkcK4BFCrWVVMKVXx/icj1njTVwWm1KYrXDVYrxf4ZLgpMH yW3SfhnXFKuxvSYnvm5EHjxtNEQIDAQAB';
}else{
$this->gateway = $this->apiurl;
$this->appid = $account['appid'];
$this->rsaPrivateKey = $account['privateKey'];
$this->alipayPublicKey = $account['publicKey']; }}/** ** initiate face to face payment * $params transmits data */
public function facepay($params){
/ / request parameter set, reference https://mp.csdn.net/editor/html/113599448
$biz_content = [
"scene"= >"bar_code".// Payment scenario Barcode payment, value: bar_code Acoustic payment, value: wave_code (required)
"out_trade_no"= >$params['pay_id'].// Unique identifier, order number (required)
"total_amount"= >$params['money'].// Order amount (optional)
"subject"= >"Buy goods".// Product name
//"seller_id" => ", // If this value is empty, it defaults to the alipay user ID corresponding to the merchant signed account
"timeout_express"= >"5m".// The latest payment time allowed for this order will close the transaction. Value range: 1 MB to 15 days. M - minutes, H - hours, D - days
];
// Public request parameters
$param = [
'app_id'= >$this->appid,// The app ID assigned by Alipay to the developer
'method'= >'alipay.trade.precreate'.// Interface name
//'format' => 'JSON',// only support JSON
'charset'= >'utf-8'.// The encoding format used in the request
'sign_type'= >'RSA2'.// Indicates the signature algorithm used by merchants to generate signature strings. Currently, RSA2 and RSA are supported. RSA2 is recommended
'sign'= >' '.// The signature string for the merchant request parameter
'timestamp' => date('Y-m-d H:i:s', time()),// Time to send the request in the format "YYYY-MM-DD HH: MM :ss"
'version'= >'1.0'.// The interface version of the call, fixed at 1.0
'notify_url'= >$params['notify_url'].// Address of asynchronous notification. Alipay server actively notifies merchant server of the specified page HTTP/HTTPS path
//'app_auth_token' => '',//app_auth_token
'biz_content' => json_encode($biz_content), // A collection of request parameters, the maximum length is unlimited, all request parameters except public parameters must be passed in this parameter
];
// Combine to generate signature parameters
$signdata = [];
$signdata['app_id'] = $param['app_id'];
$signdata['method'] = $param['method'];
$signdata['charset'] = $param['charset'];
$signdata['sign_type'] = $param['sign_type'];
$signdata['timestamp'] = $param['timestamp'];
$signdata['version'] = $param['version'];
$signdata['notify_url'] = $param['notify_url'];
$signdata['biz_content'] = $param['biz_content'];
// Generate a signature
$sign = $this->generateSign($signdata.'RSA2');
$param['sign'] = $sign;
//echo "<pre>";
//var_dump($param); die;
// Initiate a request
$content = $this->curlPost($this->gateway,$param);
$alipayData = json_decode($content.true);
// Public response parameters
$responseData = $alipayData['alipay_trade_precreate_response'];
if($responseData['code'] = =10000) {// The result is returned to the front end
$data = [];
$data['out_trade_no'] = $responseData['out_trade_no'];
$data['qr_code'] = $responseData['qr_code'];
return ['code'= >1 , 'msg'= >'success' , 'data'= >$data];
}else {
//file_put_contents(LOG_PATH .'alipayFacepay.log', 'err code:' . $responseData['code'] . ', err msg:' . $responseData['msg'] . '\r\n', FILE_APPEND);
return ['code'= >0 , 'msg'= >'Error code:' . $responseData['code'].', error message: ' . $responseData['msg']]. }}/** * Alipay payment notice *@param$data Indicates the notification data */
public function notify($data){
$falg=false;
// Verify the signature
$param = $data;
unset($param['sign']);
unset($param['sign_type']);
$rst = $this->rsaCheck($param.$data['sign'].$data['sign_type']);
if(!$rst){
file_put_contents(LOG_PATH .'alipaynotify.log'.'Failed to check \r\n' , FILE_APPEND );
return false;
}
// Query payment order status
try{
$rst = $this->orderquery($data.'TRADE_SUCCESS');
} catch (\Exception $e) {
printLog("Failed to query payment order status:".$e);
}
if($rst) {$falg=true;
}else {
file_put_contents(LOG_PATH .'alipaynotify.log'.'Error query order status \r\n', FILE_APPEND);
$falg=false;
}
return $falg;
}
/** ** payment query interface *@paramData Set of parameters in alipay response *@paramStatus Status to verify * WAIT_BUYER_PAY Transaction created waiting for buyer to pay * TRADE_CLOSED Outstanding transaction closed over time or full refund upon payment completion * TRADE_SUCCESS Transaction paid successfully * TRADE_FINISHED Closing is non-refundable */
public function orderquery($data , $status){
$biz_content = [
'out_trade_no'= >$data['out_trade_no'].'trade_no'= >$data['trade_no'].//'org_pid' => '',
];
$param = [
'app_id'= >$this->appid,
'method'= >'alipay.trade.query'.'charset'= >'utf-8'.'sign_type'= >'RSA2'.'sign'= >' '.'timestamp' => date('Y-m-d H:i:s', time()),
'version'= >'1.0'.'biz_content' => json_encode($biz_content)];// Combine signature array
$signdata = [];
$signdata['app_id'] = $param['app_id'];
$signdata['method'] = $param['method'];
$signdata['charset'] = $param['charset'];
$signdata['sign_type'] = $param['sign_type'];
$signdata['timestamp'] = $param['timestamp'];
$signdata['version'] = $param['version'];
$signdata['biz_content'] = $param['biz_content'];
// Generate a signature
$sign = $this->generateSign($signdata.'RSA2');
$param['sign'] = $sign;
$content = $this->curlPost($this->gateway,$param);
$alipayData = json_decode($content.true);
// Public response parameters
$responseData = $alipayData['alipay_trade_query_response'];
if($responseData['code'] = =10000) {if($responseData['trade_status'] = =$status) {return true;
}else {
return false; }}else {
return false; }}public function generateSign($params.$signType = "RSA") {
return $this->sign($this->getSignContent($params), $signType);
}
public function getSignContent($params) {
ksort($params);
$stringToBeSigned = "";
$i = 0;
foreach ($params as $k= >$v) {
if (false= = =$this->checkEmpty($v) && "@"! = substr($v.0.1)) {
// Convert to the target character set
$v = $this->characet($v.$this->charset);
if ($i= =0) {
$stringToBeSigned. ="$k" . "=" . "$v";
} else {
$stringToBeSigned. ="&" . "$k" . "=" . "$v";
}
$i++;
}
}
unset ($k.$v);
return $stringToBeSigned;
}
/** * Convert character set encoding *@param $data
* @param $targetCharset
* @return string
*/
function characet($data.$targetCharset) {
if (!empty($data)) {
$fileType = $this->charset;
if (strcasecmp($fileType.$targetCharset) != 0) {
$data = mb_convert_encoding($data.$targetCharset.$fileType);
//$data = iconv($fileType, $targetCharset.'//IGNORE', $data);}}return $data;
}
/** ** Verifies that $value is not empty */
protected function checkEmpty($value) {
if (!isset($value))
return true;
if ($value= = =null)
return true;
if (trim($value) = = ="")
return true;
return false;
}
/** ** Signature function */
protected function sign($data.$signType = "RSA") {
$priKey=$this->rsaPrivateKey;
$res = "-----BEGIN RSA PRIVATE KEY-----\n" .
wordwrap($priKey.64."\n".true)."\n-----END RSA PRIVATE KEY-----";
($res) or die('You are using the wrong private key format, please check the RSA private key configuration');
if ("RSA2"= =$signType) {
//OPENSSL_ALGO_SHA256 is supported only in PHP5.4.8 and later
openssl_sign($data.$sign.$res, version_compare(PHP_VERSION,'5.4.0'.'<')? SHA256 : OPENSSL_ALGO_SHA256); }else {
openssl_sign($data.$sign.$res);
}
$sign = base64_encode($sign);
return $sign;
}
/** ** check function */
public function rsaCheck($data.$sign.$type = 'RSA'){
$public_key = $this->alipayPublicKey;
$search = [
"-----BEGIN PUBLIC KEY-----"."-----END PUBLIC KEY-----"."\n"."\r"."\r\n"
];
$public_key=str_replace($search."".$public_key);
$public_key=$search[0] . PHP_EOL . wordwrap($public_key.64."\n".true) . PHP_EOL . $search[1];
$res=openssl_get_publickey($public_key);
if($res)
{
if($type= ='RSA') {$result = (bool)openssl_verify($this->getSignContent($data), base64_decode($sign), $res);
}elseif($type= ='RSA2') {$result = (bool)openssl_verify($this->getSignContent($data), base64_decode($sign), $res,OPENSSL_ALGO_SHA256);
}
openssl_free_key($res);
}else{
return false;
}
return true;
}
/* * curl Sends a post request and returns the request header * URL: access path * postData: post data to be passed * refCode: whether to return the request code * refHeader: Whether to return the request header * */
function curlPost($url.$postData.$refcode = false.$refheader = false) {
$curl = curl_init();
// Set the url to submit
curl_setopt($curl, CURLOPT_URL, $url);
// Set the retrieved information to be returned as a file stream rather than output directly
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
// Ignore certificates (turn off HTTPS authentication)
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
// Set the post mode to submit
curl_setopt($curl, CURLOPT_POST, 1);
// Set the POST data
$postFields = http_build_query($postData);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postFields);
// Add request header information
$headers = addHttpHeader($url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
// The number of seconds to wait while trying to connect
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
// Set the timeout period, the maximum execution time timeout period (unit :s)
curl_setopt($curl, CURLOPT_TIMEOUT, 300);
// Whether to return the request header (HTTP header)
if ($refheader) {
curl_setopt($curl, CURLOPT_HEADER, 1);
// Trace the request string of the handle (allow viewing request headers)
curl_setopt($curl, CURLINFO_HEADER_OUT, true);
} else {
curl_setopt($curl, CURLOPT_HEADER, 0);
}
// Execute the command
$result = curl_exec($curl);
// Convert character encoding
$result = mb_convert_encoding($result.'utf-8'.'UTF-8,GBK,GB2312,BIG5');
// Resolve invisible characters in returned JSON string that return BOM header (some editors add BOM header by default)
$result = trim($result,chr(239).chr(187).chr(191));
// Get the status code
$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
// Close the URL request
curl_close($curl);
// Whether to return the request code
if ($refcode) {
$html = array("httpcode"= >$httpcode."result"= >$result);
return $html;
} else {
return $result; }}}? >
Copy the code
2, create a pay.php payment class in app\common directory as follows:
namespace app\common;
use think\Db;
use think\Exception;
/** ** payment */
class Pay {
public $account = array(
"appid"= >"Alipay APPID"."privateKey"= >"Private key set up by merchant"."publicKey"= >"Public key automatically generated by Alipay"
);
public function startPay($params){
// Create alipay object
$alipayobj= new \pay\Alipay($this->account);
$result=$alipayobj->facepay($params);
($result['code'] = =0) && exit('Payment channel maintenance,'.$result['msg']);
// Receive the order number and payment QR code returned by Alipay
$params['out_trade_no'] = $result['data'] ['out_trade_no'];
$params['qr_code'] = $result['data'] ['qr_code'];
return $this->buildRequestForm(url('@Index/Index/facepay'),$params);
}
/**
* 服务器回调
*/
public function notify_callback($params){
// Query the order status of the database
$order = OrderModel::where('number'.$params['out_trade_no'])->find();
if(!$order) {die('No number exists ['.$params['out_trade_no'].'] order! ');
}
// Prevent malicious refresh
if ($order['status'] = =1) {
// returns success or OK directly upstream
exit('success');
}
// Create alipay object
$alipayobj= new \pay\Alipay($this->account);
// Invoke asynchronous notification validation
$verifyresult=$alipayobj->notify($params);
if ($verifyresult) {
// Actual payment amount
$money = (float)$params['total_amount'];
// Complete the business logic of the website here
exit('success');
}else{
exit('fail'); // Return failure and continue to fill the order}}/** * create a jump request form *@paramString $URL Url to which the data submission jumps@paramArray $data Array of request parameters *@paramString $method: Post or GET Default post *@returnString Submits the HTML text of the form */
function buildRequestForm($url.$data.$method = 'post'.$button_name = 'sure'.$show = false) {
$html = "<form id='requestForm' name='requestForm' action='" . $url . "' method='" . $method . "' >";
while (list($key.$val) = each($data)) {
$html. ="<input type='hidden' name='" . $key . "' value='" . $val . "' / >";
}
$display = $show ? "style='display:block; '" : "style='display:none; '";
$html. ="<input type='submit' value='" . $button_name . "'" . $display . "></form>";
$html. ="";
return $html; }}? >
Copy the code
The controller initiates a payment request
namespace app\index\controller;
use think\Controller;
use think\Cache;
use think\Session;
use think\Request;
use app\common\Pay;
class Index extends Controller
{
// Interface submission
public function submit() {
$array=array(
"pay_id"= >"Order Number"."money"= >"Order Amount"."notify_url"= >"Asynchronous notification address",);$res = (new Pay)->startPay($array);
exit($res);
}
// Pay the page in person
public function facepay(){
$data=input(' ');
!isset($data['pay_id'&&])$this->error('Order number cannot be empty');
empty(trim($data['pay_id'&&]))$this->error('Order number cannot be empty');
!isset($data['money'&&])$this->error('Amount cannot be empty');
empty(trim($data['money'&&]))$this->error('Amount cannot be empty');
!isset($data['notify_url'&&])$this->error('Asynchronous notification address cannot be empty');
empty(trim($data['notify_url'&&]))$this->error('Asynchronous notification address cannot be empty');
// Generate a QR code
$qrcode='https://my.tv.sohu.com/user/a/wvideo/getQRCode.do?width=200&height=200&text='.trim($data['qr_code']);
$this->assign('money',trim($data['money']));
$this->assign('qrcode'.$qrcode);
returnview(); }}Copy the code
That’s about it, but there are a few more features that need to be done:
- The page that displays the pay-in-person QR code, facepay.html, is the view of the facepay() method.
- Alipay in-person payment does not have the synchronous notification function, so you need to solve it yourself. The solution is to use JS timer on the facepay. HTML page to query the order status regularly. If the order is completed, it will jump to the synchronous notification page.
Finally, attached is the effect drawing I developed: