博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DELPHI微信支付代码
阅读量:5463 次
发布时间:2019-06-15

本文共 5951 字,大约阅读时间需要 19 分钟。

不管是微信支付还是支付宝支付, 3个最棘手的问题是:

1,如何生成签名
2,支付请求如何提交
3, 如何验证签名

下面就围绕这二个问题来讲。

我使用的是XE3.

先看微信支付:

1,微信支付的签名生成

uses IdHashMessageDigest, NatvieXml; //我使用的是NativeXml4.07

function TMicroPayParamBuilder.GetSign: string;

var
Digest: TIdHashMessageDigest5;
utf8: UTF8String;
begin
utf8 := '';

Assert(FAppId <> '', '公众账号ID 不能为空!');

utf8 := utf8 + 'appid=' + FAppId;
if FAttach <> '' then
utf8 := utf8 + '&attach=' + FAttach;

Assert(FAuthCode <> '', '授权码 不能为空!');

utf8 := utf8 + '&auth_code=' + FAuthCode;

Assert(FBody <> '', '商品描述 不能为空!');

utf8 := utf8 + '&body=' + FBody;

if FDetail <> '' then

utf8 := utf8 + '&detail=' + BuildDetail();

Assert(FMchId <> '', '商户号 不能为空!');

utf8 := utf8 + '&mch_id=' + FMchId;
utf8 := utf8 + '&nonce_str=' + FNonceStr;

Assert(FOutTradeNo <> '', '商户订单号 不能为空!');

utf8 := utf8 + '&out_trade_no=' + FOutTradeNo;

Assert(FSpbillCreateIp <> '', '终端IP 不能为空!');

utf8 := utf8 + '&spbill_create_ip=' + FSpbillCreateIp;

Assert(FTotalFee > 0, '订单金额 必须大于0!');

utf8 := utf8 + '&total_fee=' + IntToStr(FTotalFee);

Assert(Fkey <> '', '密钥 不能为空!');

utf8 := utf8 + '&key=' + Fkey;
//计算签名
try
Digest:= TIdHashMessageDigest5.Create;
Result := Digest.HashBytesAsHex(BytesOf(utf8));
finally
Digest.Free;
end;
end;

//生成Http Post请求的数据

function TMicroPayParamBuilder.BuildParam: string;
var
xml : TNativeXml;
Node: TXmlNode;
begin
xml := TNativeXml.CreateEx(nil, False, False, True, 'xml');
try
Node:= xml.NodeNewTextType('appid', FAppId , xeElement);
xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('mch_id', FMchId , xeElement);

xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('nonce_str', FNonceStr , xeElement);
xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('sign', Sign , xeElement);

xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('body', FBody , xeElement);

xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('out_trade_no', FOutTradeNo , xeElement);

xml.Root.NodeAdd(Node);

Node:= xml.NodeNewIntType('total_fee', FTotalFee , xeElement);

xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('spbill_create_ip', FSpbillCreateIp , xeElement);

xml.Root.NodeAdd(Node);

Node:= xml.NodeNewTextType('auth_code', FAuthCode , xeElement);

xml.Root.NodeAdd(Node);

if FAttach <> '' then

begin
Node:= xml.NodeNewTextType('attach', FAttach , xeElement);
xml.Root.NodeAdd(Node);
end;

if FDetail <> '' then

begin
Node:= xml.NodeNewTextType('detail', BuildDetail() , xeElement);
xml.Root.NodeAdd(Node);
end;

Result := xml.WriteToString;

finally

xml.Free;
end;
end;

2, 微信支付请求如何提交

class function TTencentSSLHttpPost.Post(URL: string;
Builder: TBaseParamBuilder): string;
var
ssl:TIdSSLIOHandlerSocketOpenSSL;
http: TIdHttp;
inStrm, outStrm: TStringStream;
begin
http:= TIdHttp.Create(nil);
ssl:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
ssl.SSLOptions.Method := sslvSSLv23;
http.IOHandler := ssl;
inStrm:= TStringStream.Create(Builder.BuildParam, TEncoding.UTF8);
outStrm:= TStringStream.Create('', TEncoding.UTF8);
try
try
http.Post(URL, inStrm, outStrm);
Result := outStrm.DataString;

except

Result := '';
end;
finally
ssl.Free;
http.Free;
outStrm.Free;
inStrm.Free;
end;
end;

const URL_MicroPay = 'https://api.mch.weixin.qq.com/pay/micropay';

class function TMicroPayHttpUtils.PostRequest( Builder: TMicroPayParamBuilder): string;

begin Result := TTencentSSLHttpPost.Post(URL_MicroPay, Builder);
end;

微信如何验证签名:

TStringsHelper = class helper for TStrings

function Join(const Splitter: string): string;
end;

{ TMyStrings}

function TStringsHelper.Join(const Splitter: string): string;

var
I : Integer;
begin
Result := '';
for I := 0 to Self.Count - 1 do
Result := Result + Splitter + Self.Names[I] + '=' + Self.ValueFromIndex[I];

if Result <> '' then System.Delete(result, 1, Length(Splitter));

end;
function MyStringListSort(List: TStringList; Index1, Index2: Integer): Integer;
begin
Result := CompareStr(List.Names[Index1], List.Names[Index2]);
end;

function VerifyResponseSign(xml: TNativeXml; Key: string): Boolean; overload;

var
sign: string;
I : Integer;
List : TStringList;
utf8: UTF8String;
Digest: TIdHashMessageDigest5;
begin
Result := False;

if xml.Root.FindNode('sign') = nil then Exit;

sign := xml.Root.FindNode('sign').ValueUnicode;

List := TStringList.Create;

try
for I := 0 to xml.Root.NodeCount - 1 do
begin
if (xml.Root.Nodes[I].NameUnicode <> 'sign') and (xml.Root.Nodes[I].NameUnicode <> 'WhiteSpace')
and (xml.Root.Nodes[I].ValueUnicode <> '') then
List.Add(xml.Root.Nodes[I].NameUnicode + '=' + xml.Root.Nodes[I].ValueUnicode);
end;
List.CustomSort(MyStringListSort);

utf8 := List.Join('&') + '&key=' + key;

try

Digest:= TIdHashMessageDigest5.Create;
Result := SameText(Digest.HashBytesAsHex(BytesOf(utf8)), sign);
finally
Digest.Free;
end;
finally
List.Free;
end;
end;

function VerifyResponseSign(xml: TNativeXml): Boolean; overload;

begin
Result := VerifyResponseSign(xml, GetKey());
end;

function VerifyResponseSign(Response: string; Key: string): Boolean; overload;

var
xml: TNativeXml;
begin
Result := False;
xml := TNativeXml.Create(nil);
try
try
xml.ReadFromString(Response);
except
Exit;
end;

Result := VerifyResponseSign(xml, Key);

finally
xml.Free;
end;
end;

那么如何发送一个刷卡支付请求呢?

procedure TForm4.btn4Click(Sender: TObject);
var
Param: TMicroPayParamBuilder;
Response: string;
begin
Param:= TMicroPayParamBuilder.Create;
try
if edBody.Text <> '' then
Param.Body := edBody.Text;
Param.OutTradeNo:= edTradeNo.Text;
Param.SpbillCreateIp:=idpwtch1.LocalIP;
param.AuthCode:= edAuthCode.Text;
Param.Attach := edAttach.Text;
Param.TotalFee := 10;

param.AppId := edAppId.Text;

Param.MchId := edMch_id.Text;
Param.Key := edKey.Text;

mmo1.Lines.Append(Param.BuildParam);

mmo1.Lines.Append('-------------------------------------------');

Response := TMicroPayHttpUtils.PostRequest(Param);

if Response = '' then

begin
ShowMessage('请求出错! 可能是网络不通!');
Exit;
end;

mmo1.Lines.Append(Response);

if not VerifyResponseSign(Response, GetKey()) then

showmessage('签名验证不通过!');

finally

Param.Free;
end;
end;

转载于:https://www.cnblogs.com/hnxxcxg/p/6085149.html

你可能感兴趣的文章
微信小程序-视图列表渲染
查看>>
CentOS中用户不在 sudoers 文件中。此事将被报告。
查看>>
p38 二、八、十六进制的对应关系
查看>>
Effective C++笔记——day01
查看>>
P4302 [SCOI2003]字符串折叠
查看>>
神秘的程序员
查看>>
jS 中创建对象:
查看>>
zless轻量级样式框架
查看>>
ZeroMQ接口函数之 :zmq_term - 终结ZMQ环境上下文(context)
查看>>
js获取倒计时
查看>>
loadrunner安装过程中的,注册表问题
查看>>
git push失败the remote end hung up unexpectedly
查看>>
POJ3087 Shuffle'm Up 简单模拟
查看>>
Django中数据的增删改查
查看>>
iOS模拟器发生了崩溃,去哪找Crash Log
查看>>
[支付宝]即时到账接口对接总结
查看>>
夺命雷公狗-----React---15--三元运算符
查看>>
元首的愤怒 SharePoint Apps
查看>>
CSS
查看>>
两个DataGrid垂直滚动条同步滚动
查看>>