https://www.cnblogs.com/hnxxcxg/p/6085149.html
DELPHI微信支付代码
不管是微信支付还是支付宝支付, 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的更多相关文章
- 访问路径:https://i.cnblogs.com/posts?categoryid=925678
https://i.cnblogs.com/posts?categoryid=925678
- URL https://i.cnblogs.com/EditPosts.aspx?opt=1
URL url = new URL("https://i.cnblogs.com");URL url1 = new URL(url, "EditPosts.aspx?op ...
- 随笔二-https://www.cnblogs.com/shang1680/p/9657994.html
作业要求来自https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2097 GitHub远程仓库的地址:https://github.com/ ...
- 211806189杨昊辰 https://www.cnblogs.com/honey1433223/
211806189杨昊辰 https://www.cnblogs.com/honey1433223/
- https://www.cnblogs.com/h2zZhou/p/5440271.html
https://www.cnblogs.com/h2zZhou/p/5440271.html
- https://www.cnblogs.com/soundcode/p/4174410.html
https://www.cnblogs.com/soundcode/p/4174410.html 1.首先要在服务器端新建一个网站axpx页 然后再网站的后台写代码获取winform传过来的文件名. ...
- https://www.cnblogs.com/yudanqu/p/9467803.html
https://www.cnblogs.com/yudanqu/p/9467803.html
- 转发自:一像素 十大经典排序算法(动图演示)原链接:https://www.cnblogs.com/onepixel/articles/7674659.html 个人收藏所用 侵删
原链接:https://www.cnblogs.com/onepixel/articles/7674659.html 个人收藏所用 侵删 0.算法概述 0.1 算法分类 十种常见排序算法可 ...
- @无痕客 https://www.cnblogs.com/wuhenke/archive/2012/12/24/2830530.html 通篇引用
无痕客 https://www.cnblogs.com/wuhenke/archive/2012/12/24/2830530.html 关于Async与Await的FAQ 关于Async与Await的 ...
随机推荐
- 跟我学Spring Boot(一)创建Spring Boot 项目
本人开发环境为idea15.02 + jdk8 步骤1: 步骤2: 步骤3: 步骤4: 步骤5: 相关目录介绍: resources/static:这里主要存放一些资源文件 例如 css.js.ima ...
- c#中将字符串转换成带2位小数的浮点数
今天遇到一个展示酒店价格的需求,觉得是要显示成“¥0.00”样式的,就做个小随笔,将字符串装换成带2位小数的浮点数 代码如下 "; string amount = string.Empty; ...
- Makefile 中@是什么意思
http://bbs.chinaunix.net/thread-1916415-1-1.html linux源码的顶级Makefile中有这么一句 $(filter-out _all sub-make ...
- hdu-1800(字符串hash)
题目链接:传送门 思路: 就是找最多多少个扫帚,每个扫帚上有连续递增的序列,就是找一个最多重复数字的重复次数. 由于是30位,每次用char*类型,然后用hash映射一下,排序找最多就行了. 注意: ...
- poj-3667(线段树区间合并)
题目链接:传送门 参考文章:传送门 思路:线段树区间合并问题,每次查询到满足线段树的区间最左值,然后更新线段树. #include<iostream> #include<cstdio ...
- 消除flex-wrap之后每个item上下的距离
设置flex-wrap后,每个item上下都会有距离.更改父元素的高度,就可以删除这些距离. 更改后:
- git 如何更改某个提交内容/如何把当前改动追加到某次commit上? git rebase
原文地址 http://www.jianshu.com/p/8d666830e826 [自己总结] 0, git diff git diff a b 是以a为基准,把b和a的区别展示出来 ...
- excel 错误提示以及其他基础知识
http://wenda.tianya.cn/question/05a3d11b0e4f3c34 For i = 1 To ActiveSheet.ChartObjects.Count M ...
- 代码的二次重构(开篇:JDBC连接数据库)
Java中使用JDBC连接数据库时,若是使用初级的代码,代码复用率非常低,连接过程简单来说分为以下几个步骤: 加载驱动包 准备好URL链接获取数据库连接(driver和url根据不同的数据库的不同而不 ...
- 第13章:MongoDB-聚合操作--初体验
①MongoDB 的聚合功能 MongoDB 的聚合功能,聚合操作主要用于对数据的批量处理,往往将记录按条件分组以后,然后再进行一系列操作,例如,求最大值.最小值.平均值,求和等操作. 聚合操作还能够 ...
