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的 ... 
随机推荐
- HDU 6126.Give out candies 最小割
			Give out candies Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Other ... 
- python基础之Day5
			一.基本概念 为什么要有数据: 计算机能够像人一样识别现实生活中的状态是因为计算机事先将数据存到了记忆中 为什么要分类型: 满足现实世界不同状态的需要 二.数据类型(研究定义,作用,常见操作) 1.整 ... 
- 可读性很强的C语言的函数指针定义
			通常C/C++程序里面要用到大量的指针,其语法非常难以阅读.比如下面的vp指针类型: #include <iostream> using namespace std; typedef vo ... 
- PHP 5.6 开启CURL HTTPS 类型
			前几日要写微信支付接口,微信支付接口CURL地址是HTTPS.本机测试的是OK的,但是服务器缺提示错误--“ Protocol https not supported or disabled in l ... 
- PSP(3.30——4.5)以及周记录
			1.PSP 3.30 12:00 13:00 10 50 Account前端 A Y min 13:00 13:20 0 20 站立会议 A Y min 15:15 17:00 20 85 Accou ... 
- mybatis学习 十一 缓存
			1. 应用程序和数据库交互的过程是一个相对比较耗时的过程2. 缓存存在的意义:让应用程序减少对数据库的访问,提升程序运行效率3. MyBatis 中默认 SqlSession 缓存(一级缓存)开启 同 ... 
- Java ClassLoad详解
			Java ClassLoad详解 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK 1. ... 
- com/mysql/jdbc/Driver : Unsupported major.minor version 52.0
			解决方案: 1.jdk7+老版5.0驱动com/mysql/jdbc/Driver 2.jdk8+新版6.0驱动com/mysql/cj/jdbc/Driver 
- windows中当你的键盘无法使用时我们可以用另一种方法哦
			1.使用Win+R打开cmd窗口 2.输入osk回车就出现了一个虚拟的小键盘啦,当你的键盘坏掉后非常实用哦 
- android 应用商店
			下面更多 http://wiki.youmi.net/Wiki/PromotionChannelIDs 小米 http://market.xiaomi.com/dev安智市场 http://dev.a ... 
 
			
		 
 
