Alipay mobile payment server implementation

For the interactive process of Alipay (Ant Financial) mobile payment, please refer to: https://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103658&docType=1

 

The process of WeChat payment is roughly the same, namely:

1. The client submits the order content information

2. The server generates the signed order parameters according to the signature rules according to the order content information (additional information can be added according to business needs, and the notify_url address must be specified), and returns it to the client.

Note: The server is only responsible for generating the signed order parameters, and does not need to request the Alipay server.

In the WeChat payment process, the server needs to adjust and place an order in advance to obtain the payment information of the pre-order.

3. The client calls the payment interface (the parameter is the signed order information returned by the server) to complete the payment.

4. The server receives the asynchronous notification and completes the relevant business logic.

 

# Example of order parameters:

{

    app_id : "2015052600090779",

    biz_content :{"timeout_express":"30m","seller_id":"","product_code":"QUICK_MSECURITY_PAY","total_amount":"0.01","subject":"1","body":"我是测试数据","out_trade_no":"IQJZSRC1YMQB5HU"}

    charset : "utf-8",

    format : "json",

    method : "alipay.trade.app.pay",

    notify_url : "http://domain.merchant.com/payment_notify",

    sign_type : "RSA",

    timestamp : "2016-08-25 20:26:31",

    version : "1.0"

}

 

# Server signature function:

use utf8;

use Time::Local;

use JSON;

use URI::Escape; #url encoding

 

sub alipay_get_prepay {

    my $order_info = $_[0];

 

    #Organize order parameters

    my $total_amount = sprintf("%.2f", $order_info->{rmb}+0); #Total order amount, in yuan, accurate to two decimal places, value range [0.01,100000000]

    my $PayInfo;

    $PayInfo->{app_id} = $ALIPAY_CONFIG->{appid};

    #$PayInfo->{biz_content} = {

    # body=>"recharge payment", #maximum length 128

    # out_trade_no=>$order_info->{_id}, #maximum length 64

    # product_code=>$ALIPAY_CONFIG->{product_code}, #sales product code, the product code signed by the merchant and Alipay, the maximum length is 64

    # subject=>$order_info->{order_id}, #maximum length 256

    # total_amount=>"$total_amount", #maximum length 9

    #};

    $PayInfo->{biz_content} = '{"body":"RECHAGE","out_trade_no":"'.$order_info->{_id}.'", "product_code":"'.$ALIPAY_CONFIG->{product_code}.'", "subject":"'.$order_info->{order_id}.'","total_amount":"'.$total_amount.'"}';

 

    $PayInfo->{charset} = $ALIPAY_CONFIG->{charset};

    $PayInfo->{format} = "json";

    $PayInfo->{method} = $ALIPAY_CONFIG->{method};

    $PayInfo->{notify_url} = $P_NOTIFY_URL;

    $PayInfo->{sign_type} = $ALIPAY_CONFIG->{sign_type};

    $PayInfo->{timestamp} = formateTime(time());

    $PayInfo->{version} = "1.0";

    my $ret_sign = rsa_sign($PayInfo, $ALIPAY_CONFIG->{rsa_private_key});

    $PayInfo->{sign} = $ret_sign->{sign};

    

    #对所有value(biz_content作为一个value)进行url encode

    # 请求参数说明参考官网:https://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103663&docType=1

    my $params_sign = {};

    foreach (keys %{$PayInfo}) {

        $params_sign->{$_} = uri_escape_utf8($PayInfo->{$_});

    }

    my $sign_string = join( '&', map { sprintf( '%s=%s', $_, $params_sign->{$_} ) } sort { $a cmp $b } keys %$params_sign );    # 构造签名后请求参数返回给客户端

    my $ret;

    $ret->{sign_str} = $sign_string;

    $ret->{unsign} = $ret_sign->{unsign};

    return $ret;

}

 

由于仅支持RSA或DSA的签名算法,而Perl语言尝试多次后都是签名错误,所以只好利用官方提供的Java例子,通过Perl命令行方式执行Java的RSA签名算法。具体如下:

支付宝签名规则参考:签名机制

sub rsa_sign {

    my ($params, $rsa_private_key)= @_;

    my $params_sign = {};

    foreach ( keys %$params ) {

        next if $_ eq 'sign';

        next unless defined $params->{$_};

        Encode::_utf8_off( $params->{$_} );

        $params_sign->{$_} = $params->{$_};

    }

 

    my $sign_string = join( '&',

                            map { sprintf( '%s=%s', $_, $params_sign->{$_} ) }

                            sort { $a cmp $b } keys %$params_sign );

    # 执行Java命令,得到签名结果

    my $file_path = "/var/www/app/";

    my $sign = `cd $file_path; java -cp . RSA '$rsa_private_key' '$sign_string '`;

    my $ret;

    $ret->{sign} = $sign;

    $ret->{unsign} = $sign_string;

    return $ret;

}

在/var/www/app/ 目录下需要有java的以下几个文件:

RSA.java 源文件;

以及 javac RSA.java 编译后的两个文件:

RSA$Base64.classRSA.class

 

 

 

 

 

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326122520&siteId=291194637