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: